Могут ли .NET WebApi и Angular & gt; 2 модели share или просмотреть модели [duplicate]

Без дополнительной информации трудно определить проблему, но основная причина заключается в том, что вы, скорее всего, скомпилировали класс против другой версии класса, у которой отсутствует метод, чем тот, который вы используете при его запуске .

Посмотрите на трассировку стека ... Если исключение появляется при вызове метода на объекте в библиотеке, вы, скорее всего, используете отдельные версии библиотеки при компиляции и запуске. Убедитесь, что у вас есть правильная версия обоих мест.

Если исключение появляется при вызове метода на объектах, созданных классами , которые вы сделали , то ваш процесс сборки кажется ошибочным. Убедитесь, что файлы классов, которые вы фактически запускаете, обновляются при компиляции.

97
задан wonea 25 November 2016 в 09:30
поделиться

21 ответ

В настоящее время нет ничего, что бы отображало C # в TypeScript. Если у вас много POCOs или вы думаете, что они могут часто меняться, вы можете создать конвертер - что-то простое по строкам ...

public class MyPoco {
    public string Name { get; set; }
}

To

export class MyPoco {
    public Name: string;
}

Существует также обсуждение Codeplex об автогенерации из C # .

Просто чтобы обновить содержимое, TypeLite может создавать интерфейсы TypeScript из C #:

http://type.litesolutions.net/

48
ответ дан user75525 15 August 2018 в 17:16
поделиться
  • 1
    Да, что-то вроде этого - то, что я думал делать вручную .. хорошо. Не уверен, что у меня есть время написать конвертер сейчас .. но да, это была бы идея. Благодарю. Возможно, Microsoft просто делает это прямо сейчас, пока мы говорим. – pabloelustondo 19 October 2012 в 02:57
  • 2
    Вы можете сделать это одним из двух способов: • Создать файлы .ts с помощью EnvDTE Automation или с помощью каталога каталогов Mef и отражения / интроспекции. Я предпочитаю второй, поскольку он не зависит от визуального. – Arek Bal 19 October 2012 в 08:54
  • 3
    Я начал использовать дротик и столкнулся с тем же вопросом, как делиться типами между c # и javascript. Я надеялся, что эта проблема будет решена с помощью TypScript, но похоже, что ответа еще нет. Я был немного испорчен компилятором saltarelle, который скомпилировал c # в javascript довольно красиво saltarelle-compiler.com – BraveNewMath 17 December 2012 в 15:44
  • 4
    TypeLite не работает над перечислениями, вероятно, потому, что они не доработаны до 0.9.0, которые просто попали в бета-версию. – Daniel Harvey 17 June 2013 в 15:14
  • 5
    @DanielHarvey Enums генерируются корректно с помощью TypeLite, возможно, исправленного с момента вашего комментария. – pauloya 8 July 2014 в 14:37
  • 6

Вот мой подход к его решению. Объявите свои классы C # с атрибутом, и будут создаваться файлы .d.ts (с использованием преобразований T4). Существует пакет на nuget , а источник доступен на github . Я все еще работаю над проектом, но поддержка довольно обширна.

18
ответ дан Christoffer 15 August 2018 в 17:16
поделиться

TypeLite и T4TSs выше обоих выглядели хорошо, только что выбрали один, TypeLite, разветвили его, чтобы получить поддержку для

  • ValueTypes,
  • Nullables
  • camelCasing (корневой файл TypeScript использует верблюдов, и это слишком хорошо сочетается с C #).
  • публичные поля (люблю чистые и читаемые POCOs, также упрощает создание компилятора C #)
  • отключить генерация модуля

Тогда мне нужны интерфейсы C # и подумал, что пришло время испечь мою собственную вещь и написал простой скрипт T4, который просто делает то, что мне нужно. Он также включает в себя Enums. Репо не требуется, 100 строк T4.

Использование Нет библиотеки, нет NuGet, просто этот простой простой файл T4 - используйте «добавить элемент» в Visual Studio и выберите любой шаблон T4. Затем вставьте это в файл. Адаптируйте каждую строку с помощью «ACME». Для каждого класса C # добавьте строку

<#= Interface<Acme.Duck>() #>

Вопросы порядка, любой известный тип будет использоваться в интерфейсах follwing. Если вы используете только интерфейсы, расширение файла может быть .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.

21
ответ дан citykid 15 August 2018 в 17:16
поделиться
  • 1
    Очень мило, но у вас есть typeof(ParticleKind) в вашем Enum<T>. Неужели это должно быть typeof(T)? Также вам необходимо обновить bool, чтобы быть boolean для более поздних версий TypeScript – Gone Coding 13 September 2016 в 11:44
  • 2
    Также обратите внимание: это прерывается с перечислением свойств в классах – Gone Coding 13 September 2016 в 12:15
  • 3
    1. Ух, да, спасибо за головы, это исправит. 2. Сценарий, созданный после написания этого сценария. Похоже, что может потребоваться некоторое обновление, вы, безусловно, правы. Надеюсь, это послужит отправной точкой для вашей собственной цели. – citykid 13 September 2016 в 13:42
  • 4
    Я преобразовал его в вспомогательную библиотеку, исправил ошибки и теперь использовал только однострочные записи в своих TT-файлах для создания интерфейсов и новых const enum s. Спасибо за пример. Это было очень близко, и я получил рабочий результат намного быстрее. – Gone Coding 13 September 2016 в 13:45

У меня есть небольшое решение, которое использует шаблоны T4 ( источник просмотра ).

Вы переходите от любого CLR POCO:

public class Parent : Person
{
    public string Name { get; set; }
    public bool? IsGoodParent { get; set; }
    public virtual ICollection<Child> Children { get; set; }
}

К Интерфейс TypeScript:

///<reference path="Child.d.ts" />
///<reference path="Person.d.ts" />
interface Parent extends Person {
    Name : string;
    IsGoodParent? : bool;
    Children : Child[];
}
5
ответ дан diachedelic 15 August 2018 в 17:16
поделиться

Как насчет другого пути?

Проверьте erecruit TypeScript Translator . Он поставляется с готовой поддержкой C #, но на самом деле основан на шаблонах (использует Nunjucks для рендеринга), что означает, что он может генерировать что-нибудь еще - VB.NET, F #, C ++, XML, SQL - все, что вы можете кодировать с помощью шаблона.

Работает как консольная программа .NET, программа NodeJS (для тех, кто не находится в Windows), или как расширение Visual Studio , в комплекте с функцией генерации при сохранении. И включает поддержку MSBuild, просто чтобы сделать ваш сервер сборки счастливым. : -)

2
ответ дан Fyodor Soikin 15 August 2018 в 17:16
поделиться
  • 1
    Я сделал это 1, потому что это действительно лучшее решение, сгенерированное при сохранении, являющееся функцией убийцы. – John Zabroski 24 May 2016 в 13:18

Вы также можете использовать Bridge.net. Начиная с версии 1.7, он поддерживает создание определений типа Type для типов C #. См. http://bridge.net/docs/generate-typescript-definitions/

0
ответ дан George Birbilis 15 August 2018 в 17:16
поделиться

Пожалуйста, посмотрите на эту библиотеку Typewriter

Он скрывает не только классы, перечисления, интерфейсы и т. д., но также и api-контроллеры, которые просто удивительны ..

плюс он делает, как только вы сохраняете исходный файл .cs, поэтому мне не нужно использовать какой-либо внешний инструмент для этого. Сохраните .cs, и вы получите обновление .ts

3
ответ дан harishr 15 August 2018 в 17:16
поделиться
  • 1
    Самое замечательное в том, что он создает файлы TS при сохранении соответствующих файлов CS. Однако установка выходной папки довольно хрупкая (см. обсуждение здесь ) и требует некоторого кода, созданного вручную. – Alex Klaus 1 September 2017 в 03:54
  • 2
    Для этого я использую инструменты для сборки, и этот инструмент является более мощным, чем большинство упомянутых здесь – harishr 1 September 2017 в 11:32

Если вам нужно создать отдельный файл для каждого сгенерированного класса / интерфейса TypeScript (т. е. в способе «один класс для каждого файла»), вы можете попробовать TypeGen . Это инструмент, который вы можете использовать из консоли диспетчера пакетов для создания файлов типа TypeScript на основе ваших классов / перечислений C #. В настоящее время он поддерживает:

  • экспорт перечислений; экспортирование POCO в качестве классов TS или интерфейсов
  • наследование
  • общие типы
  • коллекции / вложенные типы коллекций

плюс некоторые дополнительные функции. Это также с открытым исходным кодом (вы можете проверить это на g1] github ).

0
ответ дан JB1 15 August 2018 в 17:16
поделиться

Если кто-то хочет веб-решение, я сделал простой сайт, который преобразует классы C # DTO в интерфейсы машинописного текста. http://dto2ts.ga/ (Это еще не ошибка)

0
ответ дан karoluS 15 August 2018 в 17:16
поделиться

Я создал небольшую утилиту, которая может генерировать интерфейсы TypeScript из классов C #. Доступно как пакет NuGet . Подробную документацию можно найти на веб-странице проекта .

9
ответ дан Lukas Kabrt 15 August 2018 в 17:16
поделиться
  • 1
    Хорошая библиотека, хорошие усилия. К сожалению, не удалось найти способ изменить тип заданного значения, например. преобразовать "строку" к "KnockoutObservableString" или "строка []" к "KnockoutObservableArray". Это что-то, что есть в ближайшем будущем? – root 27 March 2013 в 17:44
  • 2
    Вместо этого я использовал T4TS, это заняло 14 минут. – root 8 April 2013 в 16:47
  • 3
    @root. Фактически вы не должны преобразовывать строку [] в KnockoutObservableArray в сгенерированные определения. Вы используете эти сгенерированные определения, когда фактически используете сериализованные экземпляры этих классов. Теперь вы можете запустить весь объект через плагин сопоставления, но я бы предостерег от этого. Это может быть чрезмерным, и я всегда предпочитаю вручную конвертировать (возможно, через ctor) из ваших сериализованных экземпляров классов C # в классы TypeScript, заполненные наблюдаемыми. Единственный раз, когда я предлагаю ослепительно запустить его через плагин отображения, - это приложение стиля CRUD. – Allen Rice 9 April 2014 в 18:34
  • 4
    @Lukas Kabrt, большое вам спасибо за TypeLite, это было очень полезно в наших проектах, и я кратко написал об этом здесь: underwatergorilladome.com/… – Allen Rice 9 April 2014 в 18:35
  • 5
    @AllenRice, мне было удобно иметь ручные классы класса нокаутов, где я использую описанный вами подход и объединять его с автоматически сгенерированным классом, который является DTO, который был передан через плагин отображения. – root 10 April 2014 в 11:04

Если вы используете Visual Studio, добавьте расширение Typewriter.

Галерея Visual Studio

Веб-сайт / документация

Обновить

С помощью Web Essentials , установленного в VS 2015, вы можете щелкнуть правой кнопкой мыши файл класса, затем> Web Essentials> Создать файл Intellisense Createcriptcript из контекстное меню.

15
ответ дан Michael Tranchida 15 August 2018 в 17:16
поделиться
  • 1
    потрясающий плагин, просто отсутствует глоток для него – harishr 18 March 2016 в 09:17
  • 2
    Он создал файл d.ts для поддержки intellisense, но как его использовать, а затем, какова связь с созданием базовых классов? Я пошел в WebEssentails и не могу найти никаких документов. Какие-либо предложения? ТИА. – howardlo 31 January 2017 в 21:28
  • 3
    @hio Просто укажите файл d.ts в любом файле .ts, который вам нужно использовать. Когда / если вы измените свой класс, базовый файл d.ts обновится. (Совет. Вы можете перетащить d.ts файл в начало файла .ts, и он создаст ссылку для вас.) – Michael Tranchida 1 February 2017 в 03:45
  • 4
    Спасибо, Майкл! Я попытался сбросить файл d.ts в пустой файл .ts, и он только добавил файл в содержащую папку. Пробовал это в VS2015 и новом VS2017, те же результаты. Знаете ли вы о каком-либо видео или учебнике, в котором показано, как все это работает? ТИА – howardlo 8 February 2017 в 01:15
  • 5
    Я попытался удалить файл d.ts в файл .ts в редакторе и создал ссылку. Думаю, теперь я понимаю. Учебник по-прежнему приветствуется. Благодаря! – howardlo 8 February 2017 в 01:27

Мое решение состояло в том, чтобы написать небольшую утилиту codegen, которая просто берет сборку проекта (и ссылается на сборки) и запускает типы сканирования, которые участвуют во взаимодействии между машинописными текстами и c #. Это использование выводит как javascript как d.ts ... Инструмент вызывается в событии после сборки ... работает как шарм!

0
ответ дан Paul0515 15 August 2018 в 17:16
поделиться
  • 1
    Я не знаю, почему я выбрал вывод js и d.ts ... прямо сейчас он просто выводит .ts ... прямо и очень выполнимо. – Paul0515 2 October 2013 в 23:30
  • 2
    Привет, Пол ... вы могли бы поделиться с нами кодом утилиты. Я просто хочу создать ts-файл (в определенном месте папки), а не файл d.ts, как вы сказали. Это то, что может сделать ваш пользователь? – Krishna Teja Veeramachaneni 30 December 2013 в 09:00

Попытайтесь создать армию. Кажется, что он решает вашу проблему.

  1. Установите его из NuGet
  2. Перейдите к вашему POCO и добавьте над ним [TsInterface] атрибут
    using Reinforced.Typings.Attributes;
    namespace YourNamespace {
        [TsInterface]
        public class YourPoco
        {
            public int YourNumber { get;set; }
            public string YourString { get;set; }
            public List<string> YourArray { get;set; }
            public Dictionary<int, object> YourDictionary { get;set; }
        }
    }
    
  3. Восстановите свой проект
  4. Найдите генерируемый код типа в файле %Your_Project_Directory%/Scripts/project.ts и добавьте его в проект вручную
    module YourNamespace {
        export interface IYourPoco
        {
            YourNumber: number;
            YourString: string;
            YourArray: string[];
            YourDictionary: { [key: int]: any };
        }
    }
    
  5. Сделайте то же самое для всех своих POCOs и ссылку project.ts в другом коде TypeScript.

Подробнее см. в документации wiki

6
ответ дан Pavel B. Novikov 15 August 2018 в 17:16
поделиться

Если вы используете 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;
}
11
ответ дан rafael 15 August 2018 в 17:16
поделиться
  • 1
    Я думаю, что люди заинтересованы в полностью автоматическом решении, в котором компиляция с помощью msbuild выводит определения типов имен до их потребления. Есть ли способ получить это с помощью плагина? – binki 13 March 2018 в 19:52
  • 2
    Нет, этот плагин VSCode работает только внутри редактора, а не как отдельная программа – rafael 13 March 2018 в 19:57

Вы можете использовать проект с открытым исходным кодом NSwag : в графическом интерфейсе вы можете выбрать .NET-класс из существующей .NET-библиотеки DLL и создать для него интерфейс TypeScript.

Проект также предоставляет инструменты командной строки и поддерживает шаблоны T4, а также создает клиентский код для контроллеров Web API ...

3
ответ дан Rico Suter 15 August 2018 в 17:16
поделиться
  • 1
    Имейте в виду, что NSwag будет генерировать TS-файлы только из двоичных файлов (вам также нужны все зависимости ваших двоичных файлов) или его JSON-файл, который Swagger производит из двоичных файлов. – Alex Klaus 1 September 2017 в 03:51

Web Essentials позволяют скомпилировать файлы C # в файлы TypeScript .d.ts при сохранении. Затем вы можете ссылаться на определения из ваших файлов .ts.

enter image description here [/g1]

31
ответ дан Robert MacLean 15 August 2018 в 17:16
поделиться
  • 1
    Возможно, вы запутались в файлах .ts и c #? не может найти эту опцию – Flores 21 July 2014 в 14:25
  • 2
    Но после некоторых поисков я нашел то, что вы имеете в виду ... на самом деле очень полезно. – Flores 21 July 2014 в 21:43
  • 3
    На самом деле это не так, я уверен, что операция «компилирует» ничего, она генерирует код. Это меня смутило, но не верно на 99%, я дам вам это ;-) – Flores 21 July 2014 в 22:10
  • 4
    Это было более полезно, если бы мы могли настроить его пространство имен и некоторую настройку. – Farshid Saberi 12 December 2015 в 19:49
  • 5
    Теперь вы должны установить «Генератор описания типов» вручную, чтобы использовать это - см. здесь – Taran 23 August 2017 в 06:14

Если вы заинтересованы, вы можете использовать TypedRpc . Его целью является не только создание интерфейсов в TypeScript, но и создание всей связи с сервисом в .Net с использованием протокола JsonRpc.

Пример для класса на сервере:

[TypedRpc.TypedRpcHandler]
public class RpcServerExample
{
    public String HelloWorld()
    {
        return "Hello World!";
    }
}

Использование сгенерированного кода TypeScript:

/// <reference path="Scripts/TypedRpc.ts" />

let rpc: TypedRpc.RpcServerExample = new TypedRpc.RpcServerExample();

var callback = function(data, jsonResponse) {
    console.log(data);
};

rpc.HelloWorld().done(callback).fail(callback);

Проверьте другие параметры использования этого параметра https://github.com/Rodris/TypedRpc .

]
0
ответ дан Rodris 15 August 2018 в 17:16
поделиться

Мне нравится решение citykid. Я немного расширил его. Таким образом, решение также основано на методе когенерации с шаблонами T4.

Он может генерировать общие типы TypeScript и эмбиентные объявления.

Он поддерживает наследование и реализации интерфейса.

Поддерживает генераторы, массивы и списки как поля типа.

Также он переводит типы TypeScript, которые явно не упоминаются в конфигурации (например, мы импортируем тип A, а в выводе TS вы можете найти некоторые другие типы : типы полей, базовые типы и интерфейсы).

Вы также можете переопределить имя типа.

Также перечислены перечисления.

Пример использования (вы можете найти его в репозитории проекта):

// set extension of the generated TS file
<#@ output extension=".d.ts" #>

// choose the type of TS import TsMode.Ambient || TsMode.Class
<# var tsBuilder = new TsBuilder(TsMode.Ambient); #>

// reference assembly with the c# types to be transformed
<#@ assembly name="$(SolutionDir)artifacts\...\CsT4Ts.Tests.dll" #>

// reference namespaces
<#@ import namespace="CsT4Ts.Tests" #>
<#
    //add types to processing
    tsBuilder.ConsiderType(typeof(PresetDTOBase), "PresetBase");
    tsBuilder.ConsiderType(typeof(PresetDTO), "Preset");
    tsBuilder.ConsiderType(typeof(TestInterface<,>));
#>

// include file with transformation algorithms
<#@ include file="CsT4Ts.t4" #>

И вы получите выход

//CsT4Ts.Tests.PresetDTOBase => PresetBase
// CsT4Ts.Tests.PresetDTO => Preset
// CsT4Ts.Tests.TestInterface`2 => TestInterface
// CsT4Ts.Tests.TestEnum => TestEnum

declare class PresetBase
{
    PresetId: string;
    Title: string;
    InterviewDate: string;
}

declare class Preset extends PresetBase
{
    QuestionsIds: string[];
}

declare interface TestInterface<TA, TB>
{
    A: string;
    B: number;
    C: TestEnum;
    D: TestEnum[];
    E: number[];
    F: TA;
    G: TB[];
}

declare enum TestEnum
{
    Foo = 10,
    Boo = 100
}

Проверьте полное решение здесь: https://bitbucket.org/ chandrush / cst4ts

1
ответ дан RollingStone 15 August 2018 в 17:16
поделиться

Вы также можете использовать это: https://github.com/pankleks/TypeScriptBuilder

Эта небольшая библиотека генерирует определение типа TypeScript на основе типов C #. Используйте его непосредственно в своем проекте C # для создания кода для вашего проекта TypeScript с интерфейсом. Вы также можете использовать небольшое консольное приложение для генерации кода с помощью инструментов предварительной сборки.

Работает на Full & amp; NET Core Framework!

Установить по nuget: Install-Package TypeScriptBuilder

Поддерживаемые функции

  • Разрешение зависимости типа
  • Generic
  • Тип наследования
  • Пространства имен (модули)
  • Перечисления
  • Нюкальные типы
  • Перевод словаря (в
  • Набор атрибутов управления генерации кода
  • any для типов, которые не могут быть преобразованы

Подробное описание : https://github.com/pankleks/TypeScriptBuilder/blob/master/README.md

2
ответ дан user1038334 15 August 2018 в 17:16
поделиться
  • 1
    Просто попробовал TypeScriptBuilder, и пока он выглядит превосходно; hooray для поддержки .NET Core! – Toby J 18 May 2017 в 15:34

Мне также очень понравился ответ @ citykid, поэтому я расширил его, чтобы сделать целое пространство имен за раз. Просто поместите классы POCO в пространство имен и перестройте шаблоны T4. Мне жаль, что я не знаю, как создавать отдельные файлы для каждого, но это не конец света.

Вам нужно ссылаться на файлы .DLL в верхней части (где вам нужны классы), и вам нужно указать пространства имен. Все строки для редактирования отмечены с помощью ACME. Познай!

<#@ template debug="true" hostSpecific="true" language="C#" #>
<#@ output extension=".ts" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ assembly name="$(TargetDir)YOUR_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ assembly name="$(TargetDir)YOUR_OTHER_DLL_NAME_HERE_ACME.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>

<#= Process("My.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>
<#= Process("My.Other.Very.Special.Namespace.ACME") #>

<#+  

    List<Type> knownTypes = new List<Type>();

    string Process(string nameSpace) {
      var allass = AppDomain.CurrentDomain.GetAssemblies();
      var ss = "";
      foreach (var ass in allass)
      {
         ss += ProcessAssembly(ass, nameSpace);
      }
      return ss;
    }

   string ProcessAssembly(Assembly asm, string nameSpace) {
      try {
            Type[] types;
            try
            {
                types = asm.GetTypes();
            }
            catch (ReflectionTypeLoadException e)
            {
                types = e.Types;
            }
            var s = "";
            foreach (var t in types.Where(t => t != null))
            {
               try {

               if (String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal))
               {
                    s += InterfaceOfType(t);
               }

               } catch (Exception e)
               {
               }
            }
            return s;      
      }
      catch (Exception ee2) {
        return "// ERROR LOADING TYPES: " + ee2;
      }

   }

    string InterfaceOfType(Type T)
    {   
        Type t = T;     
        var sb = new StringBuilder();
        sb.AppendFormat("interface {0} {{\r\n", t.Name);
        foreach (var mi in GetInterfaceMembers(t))
        {
            sb.AppendFormat("  {0}: {1};\r\n", this.ToCamelCase(mi.Name), GetTypeName(mi));
        }
        sb.AppendLine("}");
        knownTypes.Add(t);
        return sb.ToString();
    }

    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};\r\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 "boolean";
            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},\r\n", name, val);
        }
        sb.AppendLine("}");
        return sb.ToString();
    }
#>
1
ответ дан user230910 15 August 2018 в 17:16
поделиться

Ребята взгляните на https://github.com/reinforced/ Reinforced.Typings. Последние несколько дней я играю с шаблонами и t4-шаблонами и заканчиваю этот проект. Это супер-просто и работает как шарм. Просто получите пакет, измените файл конфигурации (это похоже на 10 секунд) и выполните сборку. Все делается автоматически без каких-либо проблем. Благословите автора!

Плохая вещь в шаблонах T4 заключается в том, что после сборки из VS отсканированные сборки блокируются, и вы должны перезапустить VS (как это глупо?). В T4 Toolbox + есть некоторые способы очистки VS, но ни один из них не работал для меня.

1
ответ дан veb 15 August 2018 в 17:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: