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)? 또한 업데이트해야 boolboolean나중에 타이프 라이터 버전의
코딩 사라

또한 참고 : 이것은 클래스의 열거 형 속성으로 중단됩니다
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.