TypeScript 프로젝트에서 기존 C # 클래스 정의를 재사용하는 방법


121

그냥 사용을 시작하겠습니다 TypeScript엔티티 프레임 워크 도메인 모델이 이미있는 MVC 프로젝트에 속하는 HTML 클라이언트 프로젝트에서 . 두 팀이이 작업을 수행 할 것이므로 두 프로젝트 (클라이언트 측과 서버 측)를 완전히 분리하고 싶습니다. JSON과 REST는 객체를주고받는 데 사용됩니다.

물론 domain클라이언트 측의 객체는 서버 측의 객체와 일치해야합니다. 과거에는 일반적으로이 작업을 수동으로 수행했습니다. POJOTypeScript에서 해당 클래스를 만들기 위해 내 C # 클래스 정의 (특히 내 도메인 모델 의 클래스) 를 재사용하는 방법이 있습니까?


아니요, 완전히 다른 언어입니다.
— Hans Passant

6
네, POCO를 의미했습니다. 나는 그들이 완전히 다른 언어라는 것을 알고 있습니다. 그러나 어떻게 든이 모든 것을 다시 입력하는 것을 피하는 것이 좋을 것입니다 ... 나는 잠시 동안 제 C # 코드를 복사하여 붙여 넣을 것입니다. 그리고 컴파일 될 때까지 무엇이든 리팩토링 할 것이라고 생각합니다. TypeScript ... 그런 식으로 속성을 잘못 입력하지 않았 음을 확신하고 기억할 필요가 없도록 도와줍니다. 그러나 이것은 분명히 전혀 좋지 않습니다.
— pabloelustondo

1
또한 Typescript 모델 클래스에서 JSON을 통해 양방향으로 역 직렬화 할 수있는 C # 모델 클래스에 이르기까지 다른 방향에도 관심이 있습니다.
— Jason Kleban 2013 년

나는 똑같은 것을 찾고 있었고 얼마나 많은 지원이 있는지 모르겠지만 이 Gulp 플러그인을 우연히 발견 했습니다
— Luke T O'Brien

답변:


54

현재 C #을 TypeScript에 매핑하는 것은 없습니다. POCO가 많거나 자주 변경 될 수 있다고 생각되면 변환기를 만들 수 있습니다.

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

에

export class MyPoco {
    public Name: string;
}

C #에서 자동 생성에 대한 Codeplex에 대한 토론 도 있습니다 .

업데이트를 유지하기 위해 TypeLite는 C #에서 TypeScript 인터페이스를 생성 할 수 있습니다.

http://type.litesolutions.net/


그래, 이런게 내가 수동으로하려고 생각했던 거지 .. 좋아. 지금 변환기를 작성할 시간이 있는지는 모르겠지만 .. 네, 그게 아이디어 일 것입니다. 감사. 마이크로 소프트가 우리가 말하는 동안 바로 지금하고있을 수 있습니다.
— pabloelustondo

두 가지 방법 중 하나로이 작업을 수행 할 수 있습니다. EnvDTE 자동화를 사용하거나 Mef Directory Catalog 및 Reflection / Introspection을 사용하여 .ts 파일을 생성합니다. 나는 시각적에 의존하지 않기 때문에 두 번째 것을 선호합니다.
— Arek Bal

1
나는 dart를 사용하기 시작했고 C #과 javascript간에 유형을 공유하는 방법에 대한 동일한 문제에 직면했습니다. 이 문제가 Typescript로 해결되기를 바랐지만 아직 대답이없는 것 같습니다. I 조금 오히려 근사 자바 스크립트에 # c를 컴파일 saltarelle 컴파일러 버릇도 있었다 saltarelle-compiler.com
— BraveNewMath

2
@DanielHarvey 열거 형은 TypeLite에 의해 올바르게 생성되며 귀하의 의견 이후 수정되었을 것입니다.
— pauloya

1
TypeScriptPaste는 C #을 Typescript로 변환합니다. Visual Studio 2015를 의미하는 Roslyn 컴파일러가 있어야하지만 정말 잘 작동합니다. 100 %가 아니고 일부 코드를 멍청하게 만들어야했습니다. 예를 들어 foreach를 for 루프로 변환하고, 내 자신의 List <T> 클래스를 작성하고, 내부 데이터 구조 만 사용하여 '순수'하도록 코드를 구성해야합니다. 하지만 VS에서 코드를 수정하고 테스트 한 다음 TypeScript를 통해 Javascript로 '컴파일'할 수있는 비용을 지불하는 것은 적은 비용이었습니다.
— John Mott

36

Web Essentials를 사용하면 .d.ts저장할 때 C # 파일을 TypeScript 파일 로 컴파일 할 수 있습니다. 그런 다음 .ts파일 에서 정의를 참조 할 수 있습니다.

여기에 이미지 설명 입력


.ts 파일과 C #을 혼동하고 있습니까? 이 옵션을 찾을 수 없습니다
— 플로레스

1
그러나 몇 가지 검색 후에 나는 당신이 의미하는 것을 발견했습니다.
— Flores

2
실제로는 그렇지 않습니다. 작업이 아무 것도 '컴파일'하지 않고 코드를 생성한다고 확신합니다. 그 날을 혼동하지만, 일 아닌가요은 99 % 올바른, 내가 당신에게 줄 것이다 그 ;-)
— 플로레스

1
네임 스페이스와 일부 사용자 지정을 구성 할 수 있다면 더 유용했습니다.
— Farshid Saberi

5
이제 이것을 사용하려면 'TypeScript 정의 생성기'를 수동으로 설치해야합니다. 여기를
— Taran

24

위의 TypeLite 및 T4TS는 모두 좋아 보였고 TypeLite를 선택하여 지원을 받기 위해 분기했습니다.

  • ValueTypes ,
  • Nullables
  • camelCasing (TypeScript 루트 문서는 낙타를 사용하며 C #과 함께 사용하면 너무 좋습니다)
  • 공용 필드 (깨끗하고 읽기 쉬운 POCO를 좋아하고 C # 컴파일러도 쉽게 만들 수 있음)
  • 모듈 생성 비활성화

그런 다음 C # 인터페이스가 필요 했고 이제 제 것을 구울 때라고 생각하고 필요한 작업을 수행하는 간단한 T4 스크립트를 작성했습니다. Enums 도 포함됩니다 . 리포지토리가 필요하지 않으며 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();
    }
#>

스크립트의 다음 단계는 MVC JsonController 클래스에서 서비스 인터페이스를 만드는 것입니다.


1
아주 귀여운,하지만 당신은 typeof(ParticleKind)당신에 Enum<T>. 확실히 그럴까요 typeof(T)? 또한 업데이트해야 bool할 boolean나중에 타이프 라이터 버전의
— 코딩 사라

또한 참고 : 이것은 클래스의 열거 형 속성으로 중단됩니다
— Gone Coding

1. 어, 예, 고마워요. 고쳐 줄 게요. 2. Typescript는이 스크립트를 작성한 이후로 발전했습니다. 업데이트가 필요한 것 같습니다. 확실히 맞습니다. 당신의 목적을위한 출발점이되기를 바랍니다.
— citykid

1
나는 그것을 도우미 라이브러리로 변환하고 버그를 수정했으며 이제 TT 파일에서 한 줄 항목 만 사용하여 인터페이스와 새로운 const enum. 예를 들어 주셔서 감사합니다. 매우 가까웠고 작업 결과가 훨씬 빨라졌습니다.
— Gone Coding

24

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로 컴파일하면 typescript 정의를 사용하기 전에 출력하는 완전 자동화 된 솔루션에 관심이 있다고 생각합니다. 플러그인을 사용하여 얻을 수있는 방법이 있습니까?
— binki

아니요,이 VSCode 플러그인은 편집기 내에서만 작동하며 독립형 프로그램으로는 작동하지 않습니다
— Rafael

node.js 또는 tytpescript를 통해 원하는 경우이 vscode 확장을 노드 모듈로 변환했습니다. 당신은 여기 REPO을 확인할 수 있습니다 github.com/YuvrajSagarRana/csharp-to-typescript
— 사가르라나 마 가르에게

명령을 키보드 단축키에 연결하는 방법이 있습니까? 예를 들어 .net 코드를 선택하고 "C #을 TypeScript로 변환"을 실행하기 위해 shift + ctrl + c를 설정하면 프로세스 속도가 빨라집니다. 나는 플러그인을 좋아한다!
— Pawel Cioch


18

Visual Studio를 사용하는 경우 입력기 확장을 추가합니다.

Visual Studio 갤러리

웹 사이트 / 문서

최신 정보

로 웹 필수가 VS 2015에 설치, 당신은 클래스 파일을 마우스 오른쪽 단추로 클릭 한 다음> 웹 필수> 컨텍스트 메뉴에서 타이프 라이터 인텔리 파일을 만듭니다.


intellisense 지원을 위해 d.ts 파일을 생성했지만 어떻게 사용하고 기본 클래스 생성과의 관계는 무엇입니까? WebEssentails에 갔는데 문서를 찾을 수 없습니다. 어떤 제안? TIA.
— howardlo

@hio .ts 파일에서 d.ts 파일을 사용해야합니다. 클래스를 변경하면 기본 d.ts 파일이 업데이트됩니다 (팁 : d.ts를 끌어서 놓을 수 있습니다. a의 상단에 파일은 파일을 .TS 그리고 당신에 대한 참조를 만듭니다).
— 마이클 Tranchida에게

감사합니다 마이클! d.ts 파일을 빈 .ts 파일에 놓으려고 시도했지만 포함 된 폴더에만 파일을 추가했습니다. VS2015와 새로운 VS2017에서 동일한 결과를 시도했습니다. 이 모든 것이 어떻게 작동하는지 보여주는 비디오 또는 튜토리얼을 알고 있습니까? TIA
— howardlo

d.ts 파일을 편집기의 .ts 파일에 놓아 보았고 참조를 만들었습니다. 이제 이해할 것 같아요. 튜토리얼은 여전히 ​​환영합니다. 감사!
— howardlo

@hlo 죄송합니다. 튜토리얼이 없습니다. Web Essentials 경로로 이동할 때 도메인 모델이 클래스 라이브러리에 있기 때문에 중복 .ts 파일을 만들고 있었고 클라이언트 측 코드에서 일반적으로 브라우저가 필요로하는 dto 또는 vm 모델을 만들어야합니다. 알고 있습니다. 이 모든 것에 문제가 있다면 타자기 확장을 사용해보세요. 그것은 당신이 원하는 어디서나 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. project.ts다른 TypeScript 코드에서 모든 POCO 및 참조 에 대해 동일하게 수행하십시오 .

문서 위키 에서 자세한 내용보기


오히려 단지 URL을 공유하는 샘플 코드 조각 추가
— Venkat.R


그러나 좋아, 내가 :) 여기에 예를 제공합니다
— 파벨 B. Novikov 보낸

.NET Core 지원 없음 ( 링크 ) :(
— Alex Klaus

5
@AlexKlaus .NET 코어 지원이 도착했습니다
— 파벨 B. Novikov 보낸 사람에게

10

C # 클래스에서 TypeScript 인터페이스를 생성 할 수있는 작은 유틸리티를 만들었습니다. NuGet 패키지 로 사용할 수 있습니다 . 자세한 문서는 프로젝트 웹 페이지 에서 찾을 수 있습니다 .


좋은 도서관, 좋은 노력. 불행히도 "문자열"을 "KnockoutObservableString"으로 변환하거나 "문자열 []"을 "KnockoutObservableArray"로 변환하는 것과 같이 생성 된 값 유형을 조정하는 방법을 찾지 못했습니다. 가까운 장래 계획에있는 것입니까?
— root '

2
대신 T4TS를 사용했는데 14 분이 걸렸습니다.
— root

@root, 생성 된 정의에서 실제로 string []을 KnockoutObservableArray로 변환해서는 안됩니다. 이러한 클래스의 직렬화 된 인스턴스를 실제로 사용할 때 생성 된 정의를 사용합니다. 이제 매핑 플러그인을 통해 전체 개체를 실행할 수 있지만주의해야합니다. 이는 과도 할 수 있으며, 저는 항상 C # 클래스의 직렬화 된 인스턴스에서 관찰 가능 항목으로 가득 찬 TypeScript 클래스로 (아마도 ctor를 통해) 수동으로 변환 하는 것을 선호합니다 . 매핑 플러그인을 통해 맹목적으로 실행할 것을 제안하는 유일한 시간은 CRUD 스타일 앱입니다.
— Allen Rice

@Lukas Kabrt, TypeLite에 대해 감사드립니다. 프로젝트에서 매우 유익했으며 여기에 간단히 설명을 썼습니다. underwatergorilladome.com/…
— Allen Rice

@AllenRice, 손으로 만든 Knockout 뷰 모델 클래스를 사용하는 것이 편리하다는 것을 알았습니다. 여기서 설명한 접근 방식을 사용하고 매핑 플러그인을 통해 전달 된 DTO 인 자동 생성 클래스와 결합합니다.
— 루트

7

이 도서관 타자기를 보세요

클래스, 열거 형, 인터페이스 등뿐만 아니라 api 컨트롤러도 변환합니다.

또한 소스 .cs 파일을 저장하자마자 이렇게하므로 외부 도구를 트리거 할 필요가 없습니다. .cs를 저장하면 .ts가 업데이트됩니다.


가장 좋은 점은 해당 CS 파일을 저장할 때 TS 파일을 생성한다는 것입니다. 그러나 출력 폴더를 설정하는 것은 매우 취약하고 ( 여기에서 논의 참조 ) 손으로 만든 코드가 필요합니다.
— Alex Klaus

저는이를 위해 빌드 도구를 사용합니다.이 도구는 여기에서 가장 많이 언급 한 것보다 훨씬 더 강력합니다
— 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는 바이너리 파일 (바이너리의 모든 종속성도 필요함) 또는 Swagger가 바이너리 파일에서 생성하는 JSON 파일에서만 TS 파일을 생성합니다.
— Alex Klaus

3

생성 된 모든 TypeScript 클래스 / 인터페이스에 대해 별도의 파일을 만들어야하는 경우 (예 : "파일 당 단일 클래스"방식) TypeGen 을 사용해 볼 수 있습니다 . C # 클래스 / 열거 형을 기반으로 TypeScript 파일을 생성하기 위해 패키지 관리자 콘솔에서 사용할 수있는 도구입니다. 현재 다음을 지원합니다.

  • 열거 형 내보내기; POCO를 TS 클래스 또는 인터페이스로 내보내기
  • 계승
  • 일반 유형
  • 컬렉션 / 중첩 된 컬렉션 유형

추가 기능도 있습니다. 또한 오픈 소스입니다 ( github 에서 확인할 수 있습니다 ).


2

다른 방법은 어떻습니까?

erecruit TypeScript Translator를 확인하십시오 . 바로 사용할 수있는 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 프레임 워크에서 작동합니다!

너겟으로 설치 : Install-Package TypeScriptBuilder

지원되는 기능

  • 유형 종속성 해결
  • 제네릭
  • 유형 상속
  • 네임 스페이스 (모듈)
  • 열거 형
  • Nullable 유형
  • 사전 수렴 (강력한 유형의 TS 인덱싱 된 개체로)
  • 코드 생성 제어 속성 세트
  • any 변환 할 수없는 유형

추가 설명 : https://github.com/pankleks/TypeScriptBuilder/blob/master/README.md


방금 시도했지만 TypeScriptBuilder지금까지 훌륭해 보입니다. .NET Core 지원을위한 만세!
— Tobias J

1

사람들은 https://github.com/reinforced/ Reinforced를 살펴 봅니다. . 나는 지난 며칠 동안 typelite와 t4 템플릿을 가지고 놀았고이 프로젝트를 끝냈습니다. 매우 간단하고 매력처럼 작동합니다. 패키지를 가져 와서 구성 파일을 수정하고 (10 초 동안) 빌드하면됩니다. 모든 것이 문제없이 자동으로 수행됩니다. 저자를 축복하십시오!

T4 템플릿의 나쁜 점은 VS에서 빌드하면 스캔 된 어셈블리가 잠겨 있고 VS를 다시 시작해야한다는 것입니다 (얼마나 어리석은가요?). T4 Toolbox + 일부 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 검색을 할 때 원래 질문에 도달하고 중복 / 닫힌 답변에 유용한 정보가 존재하는 것을 알지 못할 수 있다는 것입니다.
— 조지 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

내 솔루션은 단순히 프로젝트 어셈블리 (및 어셈블리 참조)를 가져오고 typescript와 c # 간의 상호 작용에 관련된 유형을 검색하는 작은 코드 생성 유틸리티를 작성하는 것이 었습니다. 이 유틸리티는 두 자바 스크립트를 d.ts로 출력합니다.이 도구는 빌드 후 이벤트에서 호출됩니다 ... 매력처럼 작동합니다!


왜 내가 js와 d.ts를 출력하기로 선택했는지 모르겠습니다. 지금은 단순히 .ts를 출력합니다. 간단하고 매우 가능합니다.
— Paul0515

1
안녕 폴 ... 유틸리티 코드를 저희와 공유해 주시겠습니까? 나는 당신이 말한 것처럼 d.ts 파일이 아닌 ts 파일 (특정 폴더 위치에)을 만들고 싶습니다. 그것은 당신의 유틸리티가 할 수있는 일입니까 ??
— Krishna Teja Veeramachaneni

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 웹 API 클라이언트 생성기 는 SDLC 중에 도구 모음 및 다른 도구 모음보다 오버 헤드가 적고 더 편리 할 수 ​​있습니다.

프로그래머는 일반적으로 WebApiClientGen을 사용하여 클라이언트 API 코드를 생성하지만이 프로젝트는 POCO 클래스에서 TypsScript 인터페이스를 생성하는 명령 줄 프로그램 인 POCO2TS.exe도 제공합니다. Poco2ts.exe 또는 poco2ts 구성 요소를 사용하여 코드 생성을 빌드 파이프 라인과 통합 할 수 있습니다.


0

node.js를 통해 변환하려면이 패키지 (csharp-to-typescript)를 사용할 수 있습니다. https://www.npmjs.com/package/csharp-to-typescript

sourcode : 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를 사용하는 경우 해당 확장 C # to TypeScript를 살펴볼 수 있습니다.

C # 클래스를 TypeScript 인터페이스로 변환

클릭 한 번으로 C # 코드에서 변환하는 방법을 확인하십시오. 물론 모든 클래스가 팩토리처럼 변환되는 것은 아니지만 클라이언트 측에서는 충분합니다. 데이터의 형태 만 있으면됩니다. 가끔 방문자 패턴을 사용해야하는 경우 필요한 추가 방법으로 꾸미겠습니다. 그렇게하는 데 5 초 밖에 걸리지 않았습니다. 위의 1 분과 비교하면 큰 승리라고 말할 수 있습니다.

내 블로그 게시물 에서 자세한 내용보기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.