टाइपलाइट और T4TS दोनों के ऊपर अच्छा लग रहा था, बस एक को टाइप किया, टाइपलाइट ने समर्थन पाने के लिए इसे छोड़ दिया
- ValueTypes ,
- Nullables
- camelCasing (टाइपप्रति जड़ दस्तावेज़ ऊंटों का उपयोग करता है, और इस के साथ सी # बहुत अच्छा एक साथ चला जाता है)
- सार्वजनिक क्षेत्र (स्वच्छ और पठनीय POCOs प्यार करते हैं, यह C # कंपाइलर के लिए भी आसान बनाता है)
- मॉड्यूल पीढ़ी को निष्क्रिय करें
तब मुझे C # इंटरफेस की आवश्यकता थी और सोचा कि यह मेरी खुद की चीज़ को सेंकने का समय है और एक साधारण T4 स्क्रिप्ट लिखी है, जो मुझे चाहिए। इसमें एनम भी शामिल है । कोई रेपो की आवश्यकता नहीं है, टी 4 की बस <100 लाइनें।
उपयोग
नहीं पुस्तकालय, कोई NuGet, बस इस सादे सरल T4 फ़ाइल - दृश्य स्टूडियो में "आइटम जोड़ें" का उपयोग करें और किसी भी T4 टेम्पलेट का चयन करें। फिर इसे फाइल में पेस्ट करें। इसमें "ACME" के साथ हर लाइन को एडॉप्ट करें। प्रत्येक C # वर्ग के लिए एक पंक्ति जोड़ें
<#= Interface<Acme.Duck>() #>
आदेश मामलों, किसी भी ज्ञात प्रकार का उपयोग फ़ॉल्विंग इंटरफेस में किया जाएगा। यदि आप केवल इंटरफेस का उपयोग करते हैं, तो फ़ाइल एक्सटेंशन .d.ts हो सकता है , एन्स के लिए आपको एक .ts फ़ाइल की आवश्यकता होती है , क्योंकि एक चर त्वरित है।
अनुकूलन
स्क्रिप्ट को हैक करें ।
<#@ template debug="true" hostSpecific="true" language="C#" #>
<#@ output extension=".ts" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ assembly name="$(TargetDir)ACME.Core.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#= Interface<Acme.Bunny>() #>
<#= Interface<Acme.Duck>() #>
<#= Interface<Acme.Birdy>() #>
<#= Enums<Acme.CarrotGrade>() #>
<#= Interface<Acme.LinkParticle>() #>
<#+
List<Type> knownTypes = new List<Type>();
string Interface<T>()
{
Type t = typeof(T);
var sb = new StringBuilder();
sb.AppendFormat("interface {0} {{\n", t.Name);
foreach (var mi in GetInterfaceMembers(t))
{
sb.AppendFormat(" {0}: {1};\n", this.ToCamelCase(mi.Name), GetTypeName(mi));
}
sb.AppendLine("}");
knownTypes.Add(t);
return sb.ToString();
}
IEnumerable<MemberInfo> GetInterfaceMembers(Type type)
{
return type.GetMembers(BindingFlags.Public | BindingFlags.Instance)
.Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property);
}
string ToCamelCase(string s)
{
if (string.IsNullOrEmpty(s)) return s;
if (s.Length < 2) return s.ToLowerInvariant();
return char.ToLowerInvariant(s[0]) + s.Substring(1);
}
string GetTypeName(MemberInfo mi)
{
Type t = (mi is PropertyInfo) ? ((PropertyInfo)mi).PropertyType : ((FieldInfo)mi).FieldType;
return this.GetTypeName(t);
}
string GetTypeName(Type t)
{
if(t.IsPrimitive)
{
if (t == typeof(bool)) return "bool";
if (t == typeof(char)) return "string";
return "number";
}
if (t == typeof(decimal)) return "number";
if (t == typeof(string)) return "string";
if (t.IsArray)
{
var at = t.GetElementType();
return this.GetTypeName(at) + "[]";
}
if(typeof (System.Collections.IEnumerable).IsAssignableFrom(t))
{
var collectionType = t.GetGenericArguments()[0]; // all my enumerables are typed, so there is a generic argument
return GetTypeName(collectionType) + "[]";
}
if (Nullable.GetUnderlyingType(t) != null)
{
return this.GetTypeName(Nullable.GetUnderlyingType(t));
}
if(t.IsEnum) return "number";
if(knownTypes.Contains(t)) return t.Name;
return "any";
}
string Enums<T>() // Enums<>, since Enum<> is not allowed.
{
Type t = typeof(T);
var sb = new StringBuilder();
int[] values = (int[])Enum.GetValues(t);
sb.AppendLine("var " + t.Name + " = {");
foreach(var val in values)
{
var name = Enum.GetName(typeof(T), val);
sb.AppendFormat("{0}: {1},\n", name, val);
}
sb.AppendLine("}");
return sb.ToString();
}
#>
स्क्रिप्ट का अगला स्तर MVC JsonController वर्ग से सेवा इंटरफ़ेस बनाने के लिए होगा।