我有一个包装API端点的WEB API代理库项目。此库将发送给需要与此Web API项目通信的C#客户端。 我需要一个生成WebAPI响应模型的T4脚本,以避免将WebAPI响应对象类型手动复制到代理库项目中。
答案 0 :(得分:0)
您可以使用以下 T4 脚本。 它管理IList,IDictionary,Nullable类型和标量类型。
假设您有ASP.NET Web API返回的响应模型类:
运行 T4 脚本(在您的代理项目中定义),您将获得以下定义:
在代理项目中定义此 T4 脚本:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output encoding="utf-8" extension=".cs"#>
<#@ assembly name="$(SolutionDir)xxx.Dis.Services.Endpoints\\bin\\Debug\\xxx.Dis.Services.Endpoints.dll" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="xxx.Dis.Services.Endpoints" #>
<# WriteLine("// ----------------------------------------------------------------------------------------------------------------");
WriteLine("// <auto-generated>");
WriteLine("// This code is automatically generated by tool on " + DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + ".");
WriteLine("// Values retrieved from project xxx.Dis.Services.Endpoints");
WriteLine("//");
WriteLine("// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.");
WriteLine("// </auto-generated>");
WriteLine("// ----------------------------------------------------------------------------------------------------------------");
WriteLine("using System;");
WriteLine("using System.Collections.Generic;");
WriteLine("using System.Linq;");
WriteLine("using System.Text;");
WriteLine("");
WriteLine("namespace xxx.Dis.Services.Api.ViewModels");
WriteLine("{");
PushIndent(" ");
// WebAPI's Enum generation
var enumList = from type in typeof(xxx.Dis.Services.Endpoints.ViewModels.Base.BaseViewModel).Assembly.GetTypes() where type.IsEnum select type;
foreach (var type in enumList)
{
WriteLine("public enum " + type.Name);
WriteLine("{");
PushIndent(" ");
foreach (var field in type.GetFields())
{
if (field.Name.Equals("value__")) continue;
WriteLine(field.Name + " = " + field.GetRawConstantValue() + ",");
}
ClearIndent();
PushIndent(" ");
WriteLine("}");
WriteLine("");
}
WriteLine("");
// WebAPI's response Models generation, filtering for all response model implementing a specific base class (in this case named BaseResponseViewModel)
var modelList = from type in typeof(xxx.Dis.Services.Endpoints.ViewModels.Base.BaseViewModel).Assembly.GetTypes() where typeof(xxx.Dis.Services.Endpoints.ViewModels.Base.BaseResponseViewModel).IsAssignableFrom(type) select type;
foreach (var type in modelList)
{
WriteLine("public class " + type.Name);
WriteLine("{");
PushIndent(" ");
foreach (var propertyInfo in type.GetProperties())
{
string propertyTypeString;
var propertyType = propertyInfo.PropertyType;
if (IsList(propertyType))
{
propertyTypeString = PrintList(propertyType);
}
else if (IsDictionary(propertyType))
{
propertyTypeString = PrintDictionary(propertyType);
}
else
{
propertyTypeString = PrintScalar(propertyType);
}
WriteLine(" public " + propertyTypeString + " " + propertyInfo.Name + " { get; set; }");
}
ClearIndent();
PushIndent(" ");
WriteLine("}");
}
ClearIndent();
WriteLine("}");
#>
<#+
public static string PrintScalar(Type type)
{
if (type.IsGenericType)
{
var genericDefionitionName = type.GetGenericTypeDefinition().Name;
if (!string.IsNullOrEmpty(genericDefionitionName) && genericDefionitionName.Contains("Nullable"))
{
var propertyType = type.GetGenericArguments()[0];
return propertyType.Name + "?";
}
}
return type.Name;
}
public static string PrintList(Type type)
{
var argumentType = type.GetGenericArguments()[0];
if (argumentType.IsGenericType && IsNullable(argumentType) == false)
{
if (IsList(argumentType))
{
return "IEnumerable<" + PrintList(argumentType) + ">";
}
if (IsDictionary(argumentType))
{
return "IEnumerable<" + PrintDictionary(argumentType) + ">";
}
}
if (IsNullable(argumentType))
{
return "IEnumerable<" + argumentType.GenericTypeArguments[0].Name + "?>";
}
return "IEnumerable<" + argumentType.Name + ">";
}
public static string PrintDictionary(Type type)
{
var argumentsTypes = type.GetGenericArguments();
// First argument must be not nullable
if (argumentsTypes[0].IsGenericType || IsNullable(argumentsTypes[0])) throw new NotSupportedException("First argument of IDictionary must be not nullable.");
var key = argumentsTypes[0].Name;
if (!argumentsTypes[1].IsGenericType) return "IDictionary<" + key + ", " + argumentsTypes[1].Name + ">";
if (IsNullable(argumentsTypes[1])) return "IDictionary<" + key + ", " + argumentsTypes[1].GenericTypeArguments[0].Name + "?>";
var innerArgumentType = argumentsTypes[1];
if (IsList(innerArgumentType))
{
return "IDictionary<" + key + ", " + PrintList(innerArgumentType) + ">";
}
if (IsDictionary(innerArgumentType))
{
return "IDictionary<" + key + ", " + PrintDictionary(innerArgumentType) + ">";
}
return IsNullable(innerArgumentType)
? "IDictionary<" + key + ", " + innerArgumentType.GenericTypeArguments[0].Name + "?>"
: "IDictionary<" + key + ", " + innerArgumentType.Name + ">";
}
public static bool IsNullable(Type t)
{
var result = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
return result;
}
public static bool IsList(Type t)
{
var result = t.IsGenericType && (t.GetGenericTypeDefinition().IsAssignableFrom(typeof(IList<>)) || t.GetGenericTypeDefinition().IsAssignableFrom(typeof(List<>)));
return result;
}
public static bool IsDictionary(Type t)
{
var result = t.IsGenericType && (t.GetGenericTypeDefinition().IsAssignableFrom(typeof(IDictionary<,>)) || t.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)));
return result;
}
#>
享受!
答案 1 :(得分:0)
ASP.NET Web API Client Generators比SDLC期间的T4模板更方便,开销更少。
尽管程序员通常使用WebApiClientGen通过jQuery或Angular2 +生成TypeScript客户端API代码,但该项目还提供了POCO2TS.exe,这是一种命令行程序,可以从POCO类生成TypsScript接口。您可以使用Poco2ts.exe或poco2ts组件将代码生成与构建管道集成在一起。