129

TypeScriptエンティティフレームワークドメインモデルがすでに存在するMVCプロジェクトに属するHTMLクライアントプロジェクトで使用を開始します。2つのチームがこれに取り組むので、2つのプロジェクト(クライアント側とサーバー側)を完全に分離したいと思います... JSONとRESTは、オブジェクトを相互に通信するために使用されます。

もちろん、domainクライアント側のオブジェクトはサーバー側のオブジェクトと一致する必要があります。以前は、通常これを手動で行っていました。C#クラス定義(特にPOJOドメインモデルのクラス)を再利用して、TypeScriptで対応するクラスを作成する方法はありますか?」

4

25 に答える 25

57

現在、C#をTypeScriptにマップするものはありません。POCOがたくさんある場合、またはPOCOが頻繁に変更される可能性があると思われる場合は、コンバーターを作成できます。

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

export class MyPoco {
    public Name: string;
}

C#からの自動生成に関するCodeplexに関する議論もあります。

物事を最新の状態に保つために、TypeLiteはC#からTypeScriptインターフェイスを生成できます。

http://type.litesolutions.net/

于 2012-10-18T16:27:06.960 に答える
39

Web Essentialsを使用すると、保存時にC#ファイルをTypeScript.d.tsファイルにコンパイルできます。次に、.tsファイルから定義を参照できます。

ここに画像の説明を入力してください

于 2014-06-18T15:33:01.630 に答える
28

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;
}
于 2016-10-04T19:30:24.153 に答える
27

上記のTypeLiteとT4TSはどちらも良さそうだったので、TypeLiteを選んだだけで、サポートを受けるためにフォークしました。

  • ValueTypes
  • Nullables
  • camelCasing(TypeScriptルートドキュメントはラクダを使用します。これはC#と組み合わせるとうまくいきます)
  • パブリックフィールド(クリーンで読みやすいPOCOが大好きで、C#コンパイラーも簡単にできます)
  • モジュール生成を無効にする

次に、C#インターフェイスが必要で、自分で作成するときが来たと思い、必要なことだけを実行する簡単なT4スクリプトを作成しました。列挙型も含まれます。レポは必要ありません。T4の100行未満です。

使用法
ライブラリなし、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();
    }
#>

スクリプトの次のレベルは、MVCJsonControllerクラスからサービスインターフェイスを作成することです。

于 2013-04-10T21:36:38.590 に答える
19

これがそれを解決するための私のアプローチです。属性を使用してC#クラスを宣言すると、.d.tsファイルが生成されます(T4変換を使用)。nugetにパッケージがあり、ソースはgithubで入手できます。私はまだプロジェクトに取り組んでいますが、サポートはかなり広範囲です。

于 2013-03-12T09:36:15.497 に答える
19

Visual Studioを使用している場合は、Typewriter拡張機能を追加します。

Visual Studio Gallery

ウェブサイト/ドキュメント

アップデート

VS2015にインストールされたWebEssentialsを使用して、クラスファイルを右クリックし、コンテキストメニューから> Web Essentials > Create TypescriptIntellisenseFileを選択できます。

于 2015-12-31T09:57:45.483 に答える
17

Reinforced.Typingsフレームワークを試してください。それはあなたの問題を解決するようです。

  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. 生成されたTypeScriptコードをファイルで見つけて、%Your_Project_Directory%/Scripts/project.ts手動でプロジェクトに追加します

    module YourNamespace {
        export interface IYourPoco
        {
            YourNumber: number;
            YourString: string;
            YourArray: string[];
            YourDictionary: { [key: int]: any };
        }
    }
    
  5. project.tsすべてのPOCOと、他のTypeScriptコードの参照について同じことを行います。

ドキュメントウィキで詳細を参照してください

于 2016-01-14T11:00:30.590 に答える
10

C#クラスからTypeScriptインターフェイスを生成できる小さなユーティリティを作成しました。NuGetパッケージとして利用できます。詳細なドキュメントは、プロジェクトのWebページにあります。

于 2013-03-19T19:59:24.227 に答える
9

このライブラリタイプライターをご覧ください

クラス、列挙型、インターフェースなどだけでなく、APIコントローラーも変換します。これは単純に素晴らしいです。

さらに、ソース.csファイルを保存するとすぐにこれが実行されるため、外部ツールをトリガーする必要はありません。.csを保存すると、更新された.tsが取得されます

于 2016-10-21T20:06:32.663 に答える
6

T4テンプレートを使用する小さなソリューションがあります(ソースを表示)。

あなたはCLRPOCOから行きます:

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[];
}
于 2013-02-01T01:11:53.473 に答える
3

オープンソースプロジェクトNSwagを使用できます。GUIでは、既存の.NET DLLから.NETクラスを選択し、そのTypeScriptインターフェイスを生成できます。

このプロジェクトは、コマンドラインツールとT4テンプレートのサポート、およびWebAPIコントローラーのクライアントコードの生成も提供します...

于 2015-11-03T08:47:47.660 に答える
3

これも使用できます:https ://github.com/pankleks/TypeScriptBuilder

この小さなライブラリは、C#型に基づいてTypeScript型定義を生成します。バックエンドC#プロジェクトで直接使用して、フロントエンドTypeScriptプロジェクトのコードを生成します。小さなコンソールアプリを作成して、ビルド前のツールでコードを生成することもできます。

Full&NET Coreフレームワークで動作します!

nugetでインストール: Install-Package TypeScriptBuilder

サポートされている機能

  • タイプの依存関係を解決する
  • ジェネリック
  • タイプ継承
  • 名前空間(モジュール)
  • 列挙型
  • null許容型
  • 辞書の収束(強い型のTSインデックス付きオブジェクトへ)
  • コード生成制御属性のセット
  • any変換できないタイプの場合

詳細:https ://github.com/pankleks/TypeScriptBuilder/blob/master/README.md

于 2016-07-28T11:05:31.120 に答える
3

生成されたTypeScriptクラス/インターフェイスごとに(つまり、「ファイルごとに1つのクラス」の方法で)個別のファイルを作成する必要がある場合は、TypeGenを試すことができます。これは、パッケージマネージャーコンソールから使用して、C#クラス/列挙型に基づいてTypeScriptファイルを生成できるツールです。現在、以下をサポートしています。

  • 列挙型のエクスポート。POCOをTSクラスまたはインターフェイスとしてエクスポートする
  • 継承
  • ジェネリック型
  • コレクション/ネストされたコレクションタイプ

加えて、いくつかの追加機能。オープンソースでもあります( githubで確認できます)。

于 2016-11-01T17:38:43.483 に答える
2

逆はどうですか?

erecruitTypeScriptTranslatorをチェックしてください。すぐに使えるC#サポートが付属していますが、実際にはテンプレートベース(レンダリングにNunjucksを使用)です。つまり、VB.NET、F#、C ++、XML、SQLなど、テンプレートでエンコードできるものなら何でも生成できます。

.NETコンソールプログラム、NodeJSプログラム(Windows以外の場合)、またはVisual Studio拡張機能として機能し、保存時に生成機能を備えています。また、ビルドサーバーを満足させるために、MSBuildのサポートが含まれています。:-)

于 2014-06-11T01:42:44.777 に答える
2

みんなはhttps://github.com/強化/Reinforced.Typingsを見てください。私はここ数日typeliteとt4テンプレートで遊んでいて、このプロジェクトに行き着きました。それは超シンプルで、魅力のように機能します。パッケージを入手し、構成ファイルを変更して(10秒間のように)、ビルドするだけです。すべてが問題なく自動的に行われます。著者を祝福してください!

T4テンプレートの悪い点は、VSからビルドすると、スキャンされたアセンブリがロックされ、VSを再起動する必要があることです(これはどれほどばかげていますか?)。T4 Toolbox +いくつかのVSクリーニングディレクティブにはいくつかの回避策がありますが、これらのどれも私にはうまくいきませんでした。

于 2015-12-18T15:56:35.233 に答える
1

私は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

于 2016-02-25T11:15:52.203 に答える
1

Bridge.netを使用することもできます。バージョン1.7から、C#タイプのTypeScript定義の生成をサポートします。http://bridge.net/docs/generate-typescript-definitions/を参照してください

于 2017-01-10T11:50:33.763 に答える
1

@citykidの回答もとても気に入ったので、一度に名前空間全体を実行するように拡張しました。POCOクラスを名前空間に配置し、T4テンプレートを再構築するだけです。それぞれに個別のファイルを生成する方法を知りたいのですが、それは世界の終わりではありません。

上部(必要なクラスがある場所)の.DLLファイルを参照する必要があり、名前空間について言及する必要があります。編集するすべての行はACMEでマークされています。@citykidへの主な称賛、感謝します!

<#@ 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();
    }
#>
于 2017-05-01T14:32:44.550 に答える
0

私の解決策は、プロジェクトアセンブリ(および参照アセンブリ)を取得し、typescriptとc#の間の相互作用に関与するタイプのスキャンを開始する小さなcodegenutilを作成することでした。このutilは、両方のjavascriptをd.tsとして出力します...ツールはビルド後のイベントで呼び出されます...チャームのように機能します!

于 2013-02-01T02:47:18.923 に答える
0

興味があれば、TypedRpcを使用できます。その目的は、TypeScriptでインターフェースを作成するだけでなく、JsonRpcプロトコルを使用して.Netでサービスとのすべての通信を作成することです。

サーバーのクラスの例:

[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を確認してください。

于 2016-12-21T13:53:12.260 に答える
0

ASP.NET Web APIクライアントジェネレーターは、SDLC中のSwaggerツールチェーンなどよりも便利でオーバーヘッドが少ない場合があります。

プログラマーは通常、WebApiClientGenを使用してクライアントAPIコードを生成しますが、このプロジェクトは、POCOクラスからTypsScriptインターフェイスを生成するコマンドラインプログラムであるPOCO2TS.exeも提供します。Poco2ts.exeまたはpoco2tsコンポーネントのいずれかを使用して、コード生成をビルドパイプラインと統合できます。

于 2019-01-29T06:27:55.980 に答える
0

node.jsを介して変換する場合は、このパッケージ(csharp-to-typescript)を使用できます。 https://www.npmjs.com/package/csharp-to-typescript

サワーコード:https ://github.com/YuvrajSagarRana/csharp-to-typescript

eg: 
// After installation, import the package.
var { CsharpToTs, getConfiguration } = require("csharp-to-typescript");

// Use CsharpToTs to convert your source code a. Method one give your source code as string:
const sourceCodeInString =   `public class Address
{
  public int Id {get; set;}
  public string Street { get; set; }
  public string City { get; set; }
}`

var outputTypescript = CsharpToTs(sourceCodeInString, getConfiguration());
console.log(outputTypescript);

// Output is

export class Address
{
  Id: number;
  Street: string;
  City: string;
}
于 2019-08-25T08:22:51.657 に答える
0

VSCodeを使用している場合は、TypeScriptの拡張機能C#を確認できます。

C#クラスをTypeScriptインターフェイスに変換します

クリックするだけでC#コードから変換する方法をご覧ください。もちろん、ファクトリのようにすべてのクラスが変換されるわけではありませんが、クライアント側には十分です。データの形が必要です。ビジターパターンを使用する必要がある場合は、必要な追加の方法で装飾することがあります。そうするのにたった5秒しかかかりませんでした。上記の1分と比較すると、大きな勝利だと言えます。

詳細については、ブログ投稿をご覧ください

于 2020-06-12T09:29:35.530 に答える
0

私はこれに関する機能リクエストを開発者コミュニティページに書きました:

https://developercommunity.visualstudio.com/idea/1153873/reuse-existing-net-classes-for-typescript-definiti.html

ここでの回答からわかるように、これを解決しようとするプロジェクトはたくさんありますが、残念ながら、これらのプロジェクトの多くは、途中でサポートされなくなった単一の開発者プロジェクトです。.NETマイクロソフトが代わりにこれらのプロジェクトの1つを維持し、 toTypeScriptジェネレーターを作成するのは本当に素晴らしいことだと思います。

とりわけ、一部はまだ維持されていますが、単一の開発者に大きく依存しています。

TypeLite:

https://bitbucket.org/LukasKabrt/typelite/src/default/

TypeScript定義ジェネレーター:

https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TypeScriptDefinitionGenerator

タイプライター:

https://github.com/frhagn/Typewriter

TypeGen:

https://github.com/jburzynski/TypeGen

強化。入力:

https://github.com/forced/Reinforced.Typings

私のヒントは、最初から維持されなくなると予想され、現在維持されているものに切り替える準備ができているプロジェクトを選択することです。注釈を使用するものを探して指を交差させると、そのプロジェクトがサポートされなくなった場合に、そのタグを別のタグに置き換えることができます。

于 2020-08-18T12:58:13.377 に答える
0

TypeScriptクラスとC#DTO/POCOクラスの両方を生成する小さなカスタムDSLを使用しています。DSLは次のようになります。

output CSharp
output TypeScript

namespace MyLibrary.Logic.DataModel.DTOs

class Something

property int ID
property string Name
property DateTime DateTime
property int ForeignKeyID

このようにして、単一のソース(DSL)を持ち、2つのC#ロジックモデルとTypeScriptロジックモデルの間に位置するDTOモデルがあります。

次に、DTOとロジックモデルオブジェクト間の変換を担当するメソッドを持つC#クラスとTypeScriptDTOFactoryクラスの両方を記述します。(そして、DTO生成の一部は、シリアル化またはIndexedDBに格納するために匿名のJSONに適したタイプに変換するシリアル化メソッドです。)

これを行うことにより、どちらかの側でモデルが変更されるとすぐに、両方の側が再び一致するまでコンパイルエラーが発生します。

于 2021-05-28T16:54:15.953 に答える