简体   繁体   English

使用T4为代理的ASP.NET Web API创建C#模型类

[英]Create C# model class for proxy's ASP.NET Web API using T4

I have a WEB API proxy library project that wrap API endpoints. 我有一个包装API端点的WEB API代理库项目。 This library is shipped to C# clients that need to communicate with this Web API project. 该库已交付给需要与此Web API项目进行通信的C#客户端。 I need a T4 script that generate WebAPI response models, in order to avoid manual copy of WebAPI response object type into proxy library project. 我需要一个生成WebAPI响应模型的T4脚本,以避免将WebAPI响应对象类型手动复制到代理库项目中。

You can use the following T4 script. 您可以使用以下T4脚本。 It manage IList, IDictionary, Nullable type and scalar type. 它管理IList,IDictionary,Nullable类型和标量类型。

Assuming you have this response model class returned by your ASP.NET Web API: 假设您的ASP.NET Web API返回了此响应模型类:

Web API响应模型类型

Running the T4 script (defined in your proxy project) you will get this definition: 运行T4脚本(在代理项目中定义),您将获得以下定义:

T4模型类生成类型

Define this T4 script in your proxy project: 在您的代理项目中定义此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;
    }
#>

Enjoy! 请享用!

ASP.NET Web API Client Generators may be more handy, less overhead than T4 templates during SDLC. 与SDLC期间的T4模板相比, ASP.NET Web API客户端生成器可能更方便,开销更少。

While programmers generally use WebApiClientGen to generate TypeScript client API codes with jQuery or Angular2+, this project also provides POCO2TS.exe, a command line program that generates TypsScript interfaces from POCO classes. 尽管程序员通常使用WebApiClientGen通过jQuery或Angular2 +生成TypeScript客户端API代码,但该项目还提供了POCO2TS.exe,这是一种命令行程序,可从POCO类生成TypsScript接口。 You may use either Poco2ts.exe or the poco2ts component to integrate the code generation with your build pipeline. 您可以使用Poco2ts.exe或poco2ts组件将代码生成与构建管道集成在一起。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用c#在asp.net中动态创建网页 - Dynamically create web page in asp.net using c# 自行生成SOAP Web服务代理对象的代码-C#/。NET 3.5 / T4 - Code generating SOAP Web Service Proxy objects yourself - C#/.NET 3.5/T4 如何在ASP.NET中使用C#创建动态类 - how to create dynamic class using c# in asp.net 如何在Asp.NET Core WEB API中使用.Net(C#)在有效载荷中使用自定义JSON声明创建JWT令牌 - How to create a JWT token with custom JSON claims in Payload using .Net (C#) in Asp.NET Core WEB API C#ASP.Net:如何在不使用WSDL或代理类的情况下在.NET 4.0 C#中调用Web服务 - C# ASP.Net : How to call a web service in .NET 4.0 C# without using the WSDL or proxy classes C#ASP.NET Web API中的模型验证日期格式 - Model validate date format in c# asp.net web api asp.net core web api 2中的抽象类模型绑定 - Abstract class model binding in asp.net core web api 2 如何在 Web API 模型 ASP.NET 中隐藏嵌套类 - How to hide the nested class in Web API Model ASP.NET 使用ASP.NET的简单反向代理,带有身份验证的C# - A simple reverse proxy using ASP.NET, C# with authentication 如何创建使用String作为其搜索参数的get方法?(asp.net Web API C#) - How to create get method that uses String as its search parameter?(asp.net web api C#)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM