Создайте класс модели C# для веб-API ASP.NET прокси с помощью T4

У меня есть проект прокси-библиотеки WEB API, который обертывает конечные точки API. Эта библиотека поставляется клиентам C#, которым необходимо взаимодействовать с этим проектом веб-API. Мне нужен сценарий T4, который генерирует модели ответа WebAPI, чтобы избежать ручного копирования типа объекта ответа WebAPI в проект библиотеки прокси.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
651
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать следующий сценарий Т4. Он управляет IList, IDictionary, типом Nullable и скалярным типом.

Предполагая, что у вас есть этот класс модели ответа, возвращенный вашим веб-API ASP.NET:

Web API response model type

Запустив сценарий Т4 (определенный в вашем прокси-проекте), вы получите следующее определение:

T4 model class generated type

Определите этот сценарий Т4 в своем прокси-проекте:

<#@ 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;
    }
#>

Наслаждаться!

Генераторы клиентов веб-API ASP.NET может быть более удобным, меньше накладных расходов, чем шаблоны T4 во время SDLC.

Хотя программисты обычно используют WebApiClientGen для генерации кодов клиентского API TypeScript с помощью jQuery или Angular2 +, этот проект также предоставляет POCO2TS.exe, программу командной строки, которая генерирует интерфейсы TypsScript из классов POCO. Вы можете использовать либо Poco2ts.exe, либо компонент poco2ts для интеграции генерации кода с конвейером сборки.

Другие вопросы по теме