如何在TypeScript项目中重用现有的C#类定义


121

我将开始TypeScript在我的HTML客户端项目中开始使用该项目,该项目属于具有实体框架域模型的MVC项目。我希望我的两个项目(客户端和服务器端)完全分开,因为两个团队将在此上工作... JSON和REST用于来回通信对象。

当然,我domain在客户端的对象应该与服务器端的对象匹配。过去,我通常是手动完成此操作。有没有一种方法可以重用我的C#类定义(特别是POJO我的域模型中的类)来在TypeScript中创建相应的类”?


不,它们是完全不同的语言。
汉斯·帕桑

6
是的,我是说POCO。我知道它们是完全不同的语言...但是最好以某种方式避免再次键入所有这些内容...我认为目前我将复制并粘贴我的C#代码..并将对其进行任何重构,直到将其编译为TypeScript ...这样,我确定我没有键入错误的属性..并帮助我不必记住。但这显然听起来并不好。
pabloelustondo 2012年

1
我还对另一个方向感兴趣-从Typescript模型类到C#模型类,可以通过JSON双向反序列化。
杰森·克莱本

我一直在寻找相同的东西,但我偶然发现了这个Gulp插件,尽管我不知道它有多少支持
Luke T O'Brien

Answers:


54

当前没有任何可将C#映射到TypeScript的东西。如果您有很多POCO,或者您认为它们可能经常更改,则可以创建一个转换器-类似于以下内容的简单方法:

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

export class MyPoco {
    public Name: string;
}

在Codeplex上也有关于从C#自动生成讨论

只是为了保持更新,TypeLite可以从C#生成TypeScript接口:

http://type.litesolutions.net/


是的,这样的事情就是我想手动完成的。不知道我现在有时间写一个转换器..是的,那是个主意。谢谢。也许是微软现在就在做。
pabloelustondo 2012年

您可以通过以下两种方式中的任何一种来执行此操作:在EnvDTE Automation的帮助下或通过使用Mef目录目录和反射/自省生成.ts文件。我喜欢第二个,因为它不依赖视觉。
阿雷克·巴尔

1
我开始使用dart,遇到了如何在c#和javascript之间共享类型的同一问题。我希望Typescript可以解决此问题,但似乎尚未找到答案。Saltarelle-compiler也让我有点受宠若惊,该编译器将C#编译为javascript相当不错的saltarelle-compiler.com
BraveNewMath 2012年

2
@DanielHarvey枚举由TypeLite正确生成,可能在您评论后已修复。
pauloya 2014年

1
TypeScriptPaste会将C#转换为Typescript。您必须拥有Roslyn编译器,这意味着Visual Studio 2015,但是它确实运行良好。它不是100%,我不得不精简一些代码-例如,将foreach转换为for循环,编写我自己的List <T>类,并且您必须对代码进行结构化,使其仅包含内部数据结构即可“纯净”可以使用,但是要能够在VS中修改和测试代码,然后通过TypeScript将其“编译”为Javascript,付出的代价很小。
约翰·莫特

36

Web Essentials允许.d.ts在保存时将C#文件编译为TypeScript 文件。然后,您可以引用.ts文件中的定义。

在此处输入图片说明


您可能会混淆.ts文件和c#?找不到此选项
Flores

1
但是经过一番搜索,我发现了你的意思..实际上很有用。
Flores

2
其实不是,我很确定该操作什么都不会“编译”,它会生成代码。那让我感到困惑,但不是99%正确,我给你;-)
Flores

1
如果我们可以配置其名称空间和进行一些自定义,它会更有用。
Farshid Saberi 2015年

5
您现在必须手动安装“ TypeScript Definition Generator”才能使用它-参见此处
-Taran

24

上面的TypeLite和T4TS看起来都不错,只是选了一个TypeLite,分叉得到了它的支持

  • ValueTypes
  • 空值
  • camelCasing(TypeScript根文档使用骆驼,与C#一起使用时效果很好)
  • 公共字段(喜欢干净且可读的POCO,也使C#编译器更容易使用)
  • 禁用模块生成

然后我需要C#接口并认为是时候烘焙自己的东西并编写一个简单的T4脚本来满足我的需要了。它还包括Enums。不需要回购协议,只需<100行T4。

用法
没有库,没有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();
    }
#>

脚本的下一个级别将是从MVC JsonController类创建服务接口。


1
很可爱,但你必须typeof(ParticleKind)在你的Enum<T>。当然应该typeof(T)吗?另外,您还需要更新boolboolean用于更高版本的TypeScript
Gone Coding

另请注意:这与类中的枚举属性中断
Gone Coding

1.嗯,是的,谢谢您的注意,将解决此问题。2.自从编写此脚本以来,Typescript就得到了发展。看起来可能需要一些更新,您当然是对的。我希望它可以作为您自己目的的起点。
citykid

1
我将其转换为帮助程序库,修复了错误,现在仅在TT文件中使用单行条目来生成接口和新const enum的。谢谢你的例子。距离非常近,可以让我更快地获得工作结果。
Gone Coding

23

如果您使用vscode,则可以使用我的扩展名csharp2ts来做到这一点。

您只需选择粘贴的C#代码并Convert C# to TypeScript从命令面板在此处输入图片说明 A转换示例中运行命令 :

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

1
我认为人们对一种完全自动化的解决方案感兴趣,该解决方案是在使用msbuild进行编译之前先输出打字稿定义的。有没有办法使用插件来做到这一点?
宾基

不,这是一个VSCode插件,仅在编辑器内部可用,而不能作为独立程序运行
Rafael

如果您想通过node.js或tytpescript,我已将此vscode扩展转换为节点模块。您可以在此处查看该存储库:github.com/YuvrajSagarRana/csharp-to-typescript
Sagar Rana Magar

有没有办法将命令链接到键盘快捷键?例如,将选择.net代码,并设置shift + ctrl + c来执行“将C#转换为TypeScript”,这将加快处理速度。我喜欢这个插件!
Pawel Cioch


18

如果您使用的是Visual Studio,请添加Typewriter扩展。

Visual Studio画廊

网站/文件

更新资料

随着网络要点安装在VS 2015年,您可以右键单击类文件,然后>网络要点>创建从上下文菜单中打字稿智能感知文件。


它创建了d.ts文件以提供智能支持,但是如何使用它,然后与创建基础类有什么关系?我去了WebEssentails,找不到任何文档。有什么建议?TIA。
howardlo

@hio只需在需要使用的任何.ts文件中引用d.ts文件即可。当/如果更改类,则基础d.ts文件将更新。(提示:您可以拖放d.ts文件到.ts文件的顶部,它将为您创建引用。)
Michael Tranchida

谢谢迈克尔!我尝试将d.ts文件拖放到一个空的.ts文件中,但它仅将该文件添加到了包含文件夹中。在VS2015和新版VS2017中进行了尝试,结果相同。您是否知道任何视频或教程可以显示这一切的工作原理?TIA
howardlo

我尝试将d.ts文件放入编辑器中的.ts文件,并创建了引用。我想我现在明白了。教程仍然很受欢迎。谢谢!
howardlo

@hlo抱歉,没有任何教程。当我走Web Essentials路线时,我一直在制作重复的.ts文件,因为我的域模型在类库中,并且在我的客户端代码中,我通常需要创建dto或vm模型,浏览器需要这样做。知道关于。如果您在所有这些方面都遇到问题,请尝试使用Typewriter扩展。它使您可以在任意位置拥有ur .ts模型文件。
Michael Tranchida

15

尝试使用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. %Your_Project_Directory%/Scripts/project.ts文件中找出生成的TypeScript代码并将其手动添加到项目中

    module YourNamespace {
        export interface IYourPoco
        {
            YourNumber: number;
            YourString: string;
            YourArray: string[];
            YourDictionary: { [key: int]: any };
        }
    }
  5. 对所有POCO都执行相同的操作,并project.ts在其他TypeScript代码中进行引用。

文档Wiki中查看更多详细信息


添加示例代码段,而不是仅共享URL
Venkat.R


但是好吧,我将在此处提供一个示例:)
Pavel B. Novikov

没有.NET Core支持(链接):(
Alex Klaus

5
@AlexKlaus .NET Core支持已经到达
Pavel B. Novikov

10

我创建了一个小的实用程序,可以从C#类生成TypeScript接口。作为NuGet软件包提供。详细的文档可以在项目网页上找到。


不错的图书馆,很努力。不幸的是,没有找到一种调整产生值类型的方法,例如将“ string”转换为“ KnockoutObservableString”或将“ string []”转换为“ KnockoutObservableArray”。这是不久的将来的计划吗?

2
我改用T4TS,花了14分钟。

@root,您实际上不应在生成的定义中将string []转换为KnockoutObservableArray。在实际使用这些类的序列化实例时,可以使用这些生成的定义。现在,您可能正在通过映射插件运行整个对象,但是我要提醒您注意这一点。这可能太过分了,我始终喜欢手动(可能通过ctor)从您的C#类的序列化实例转换为可观察到的TypeScript类。我唯一一次建议通过映射插件盲目运行它是针对CRUD风格的应用程序。
艾伦·赖斯

@Lukas Kabrt,非常感谢TypeLite,它对我们的项目非常有益,我在这里简要介绍了一下:underwatergorilladome.com/…–
Allen Rice

@AllenRice,我发现手工制作Knockout视图模型类非常方便,在这里我可以使用您所描述的方法,并将其与自动生成的类(通过映射插件传递的DTO)相结合。

7

请看一下这个库打字机

它不仅可以转换类,枚举,接口等,还可以转换api-controllers,这真是太棒了。

另外,保存源.cs文件后,它便会执行此操作,因此我不必触发任何外部工具。保存.cs,您将获得更新的.ts


很棒的是,它会在保存相应的CS文件时生成TS文件。但是,设置输出文件夹非常脆弱(请参阅此处的讨论),并且需要一些手工编写的代码。
亚历克斯·克劳斯

我确实使用了构建工具,并且该工具比这里提到的大多数工具功能更强大
harishr

6

我有一个使用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[];
}

3

您可以使用开源项目NSwag:在GUI中,可以从现有的.NET DLL中选择.NET类,并为其生成TypeScript接口。

该项目还提供命令行工具和对T4模板的支持,以及为Web API控制器生成客户端代码...


请注意,NSwag只会从二进制文件(也需要二进制文件的所有依赖项)或其JSON文件(由Swagger从二进制文件生成)中生成TS文件。
亚历克斯·克劳斯

3

如果您需要为每个生成的TypeScript类/接口创建一个单独的文件(即以“每个文件一个类”的方式),则可以尝试TypeGen。您可以从Package Manager控制台使用该工具,根据您的C#类/枚举生成TypeScript文件。目前支持:

  • 出口枚举;将POCO导出为TS类或接口
  • 遗产
  • 通用类型
  • 集合/嵌套集合类型

加上一些其他功能。它也是开源的(您可以在github上查看)。


2

反过来呢?

查看erecruit TypeScript转换器。它具有随时提供C#支持的功能,但实际上是基于模板的(使用Nunjucks进行渲染),这意味着它可以生成其他任何内容-VB.NET,F#,C ++,XML,SQL-可以使用模板进行编码的任何内容。

具有.NET控制台程序,NodeJS程序(适用于Windows以外的程序)或Visual Studio扩展程序,具有保存时生成功能。并包括MSBuild支持,只是为了使您的构建服务器满意。:-)


我为此+1,因为它确实是最好的解决方案,保存时生成是杀手级功能。
John Zabroski

2

您还可以使用以下命令: https //github.com/pankleks/TypeScriptBuilder

这个小库基于C#类型生成TypeScript类型定义。直接在您的后端C#项目中使用它来为您的前端TypeScript项目生成代码。您还可以编写小型控制台应用程序,以通过预构建工具生成代码。

适用于Full&NET Core框架!

通过nuget安装: Install-Package TypeScriptBuilder

支持的功能

  • 解决类型依赖
  • 泛型
  • 类型继承
  • 命名空间(模块)
  • 枚举
  • 可空类型
  • 字典收敛(到强类型TS索引对象)
  • 代码生成控件属性集
  • any 对于无法转换的类型

更多描述:https//github.com/pankleks/TypeScriptBuilder/blob/master/README.md


刚刚尝试过TypeScriptBuilder,到目前为止看起来还不错;hooray for .NET Core支持!
Tobias J

1

大家看看https://github.com/reinforced/ Reinforced.Typings。最近几天,我一直在使用typelite和t4模板,并最终完成了这个项目。它非常简单,就像魅力一样。只需获取软件包,修改配置文件(大约10秒钟)并构建即可。全部自动完成,没有任何问题。祝福作者!

T4模板的坏处是,从VS构建后,扫描的程序集将被锁定,并且必须重新启动VS(这有多愚蠢?)。T4工具箱中有一些解决方法+一些VS清洁指令,但是这些都不适合我。


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


1

您也可以使用Bridge.net。从1.7版开始,它支持为C#类型生成TypeScript定义。参见http://bridge.net/docs/generate-typescript-definitions/


主要问题是,当您进行Google搜索时,您可能会发现原始问题,而永远不会注意到有用的信息存在于重复/封闭的答案中
George Birbilis

因此,请确保规范资料具有最佳信息。不要发布多个问题。有关此问题的任何进一步讨论,可以参考Meta Stack Overflow
Martijn Pieters

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();
    }
#>

0

我的解决方案是编写一个小的codegen util,它仅需要一个项目程序集(和引用程序集),并开始扫描Typescript和c#之间的交互所涉及的类型。该实用程序将javascript都输出为d.ts ...在构建后事件中调用该工具...就像一个吊饰!


我不知道为什么我选择输出js和d.ts ...现在它只输出.ts ...简单易行。
Paul0515

1
嗨,保罗...您能与我们分享该实用程序代码。我希望仅创建ts文件(在特定文件夹位置),而不是像您说的那样创建d.ts文件。这是您的效用者可以做的事情吗?
克里希纳·特雅·维拉玛卡尼尼

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,以获取有关如何使用它的其他示例。


0

ASP.NET Web API客户端生成器与SDLC期间的灵活工具链和其他工具相比,可能更方便,开销更少。

尽管程序员通常使用WebApiClientGen生成客户端API代码,但该项目还提供POCO2TS.exe,这是一个命令行程序,可以从POCO类生成TypsScript接口。您可以使用Poco2ts.exe或poco2ts组件将代码生成与构建管道集成在一起。


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

0

如果您使用的是VSCode,则可以查看TypeScript的C#扩展名

将C#类转换为TypeScript接口

只需单击一下,即可查看如何从C#代码转换它。当然,并非所有类都将被转换,例如工厂,但是对于客户端而言已经足够了。我们只需要数据的形状。有时,如果我需要使用访客模式,我将用所需的其他方法来装饰。这样做只花了5秒钟。与上面的一分钟相比,我可以说这是一个巨大的胜利。

在我的博客文章中查看更多详细信息

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.