TypeLite và T4TS ở trên đều có vẻ tốt, chỉ cần chọn một cái, TypeLite, chia nhỏ nó để được hỗ trợ
- ValueTypes ,
- Nullables
- camelCasing (tài liệu gốc của TypeScript sử dụng lạc đà và điều này rất tốt khi kết hợp với C #)
- các trường công cộng (yêu thích các POCO sạch và dễ đọc, cũng giúp cho Trình biên dịch C # trở nên dễ dàng)
- vô hiệu hóa tạo mô-đun
Sau đó, tôi cần các giao diện C # và nghĩ rằng đã đến lúc nướng thứ của riêng mình và viết một tập lệnh T4 đơn giản chỉ làm những gì tôi cần. Nó cũng bao gồm Enums . Không cần repo, chỉ cần <100 dòng T4.
Cách sử dụng
Không có thư viện, không có NuGet, chỉ cần tệp T4 đơn giản này - sử dụng "thêm mục" trong Visual Studio và chọn bất kỳ mẫu T4 nào. Sau đó, dán nó vào tệp. Điều chỉnh mọi dòng với "ACME" trong đó. Đối với mỗi lớp C #, hãy thêm một dòng
<#= Interface<Acme.Duck>() #>
Vấn đề đặt hàng, bất kỳ loại nào đã biết sẽ được sử dụng trong các giao diện follwing. Nếu bạn chỉ sử dụng giao diện, phần mở rộng tệp có thể là .d.ts , đối với enums, bạn cần tệp .ts , vì một biến được khởi tạo.
Tùy chỉnh
Hack kịch bản.
<#@ 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();
}
#>
Cấp độ tiếp theo của script sẽ là tạo giao diện dịch vụ từ lớp MVC JsonController.