我将开始TypeScript
在我的 HTML 客户端项目中使用,该项目属于一个 MVC 项目,其中已经存在实体框架域模型。我希望我的两个项目(客户端和服务器端)完全分开,因为两个团队将致力于此……JSON 和 REST 用于来回通信对象。
当然,我domain
在客户端的对象应该与服务器端的对象匹配。过去,我通常手动完成此操作。有没有办法重用我的 C# 类定义(特别是POJO
我的域模型中的类)来在 TypeScript 中创建相应的类”?
我将开始TypeScript
在我的 HTML 客户端项目中使用,该项目属于一个 MVC 项目,其中已经存在实体框架域模型。我希望我的两个项目(客户端和服务器端)完全分开,因为两个团队将致力于此……JSON 和 REST 用于来回通信对象。
当然,我domain
在客户端的对象应该与服务器端的对象匹配。过去,我通常手动完成此操作。有没有办法重用我的 C# 类定义(特别是POJO
我的域模型中的类)来在 TypeScript 中创建相应的类”?
目前没有任何东西可以将 C# 映射到 TypeScript。如果您有很多 POCO 或者您认为它们可能经常更改,您可以创建一个转换器 - 一些简单的东西......
public class MyPoco {
public string Name { get; set; }
}
到
export class MyPoco {
public Name: string;
}
在 Codeplex 上还有一个关于从 C# 自动生成的讨论。
为了保持更新,TypeLite 可以从 C# 生成 TypeScript 接口:
Web Essentials允许.d.ts
在保存时将C# 文件编译为 TypeScript文件。然后你可以从你的.ts
文件中引用定义。
如果您使用 vscode,您可以使用我的扩展csharp2ts,它正是这样做的。
您只需选择粘贴的 C# 代码并Convert C# to TypeScript
从命令面板运行命令
一个转换示例:
public class Person
{
/// <summary>
/// Primary key
/// </summary>
public int Id { get; set; }
/// <summary>
/// Person name
/// </summary>
public string Name { get; set; }
}
到
export interface Person
{
/**Primary key */
Id : number;
/**Person name */
Name : string;
}
上面的 TypeLite 和 T4TSs 看起来都不错,就挑了一个,TypeLite,fork 得到支持
然后我需要 C#接口并认为是时候烘焙我自己的东西并编写了一个简单的 T4 脚本来满足我的需要。它还包括Enums。不需要 repo,只需 < 100 行 T4。
用法
没有库,没有 NuGet,只有这个简单的 T4 文件 - 在 Visual Studio 中使用“添加项目”并选择任何 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 类创建服务接口。
这是我解决它的方法。使用属性声明您的 C# 类,然后将生成 .d.ts 文件(使用 T4 转换)。nuget 上有一个包,源代码可在 github 上找到。我仍在从事该项目,但支持非常广泛。