129 votes

Comment réutiliser des définitions de classe C # existantes dans des projets TypeScript

Je vais juste commencer à utiliser la Machine dans mon HTML de projet du client qui appartient à un projet MVC avec une entité cadre du modèle de domaine déjà là. Je veux que mes deux projets (côté client et côté serveur) totalement séparé en deux équipes vont travailler sur ce... JSON et le RESTE est utilisé pour communiquer les objets d'avant en arrière.

Bien sûr, mon "domaine" des objets sur le côté client devrait correspondre les objets sur le côté serveur. Dans le passé, j'ai normalement fait manuellement. est-il un moyen de réutiliser mon C# définitions de classe (spécialement des classes POJO dans mon modèle de domaine) pour créer des classes correspondant à la machine". Merci?

56voto

Steve Fenton Points 55265

Il n'y a pas actuellement de quelque chose qui va de la carte C# de caractères d'imprimerie. Si vous avez beaucoup de POCOs ou vous pensez qu'ils pourraient changer souvent, vous pouvez créer un convertisseur simple quelque chose le long des lignes de...

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

Pour

export class MyPoco {
    public Name: string;
}

Il y a aussi une discussion sur Codeplex à propos de l'auto-génération à partir de C#.

Juste pour garder les choses jour, TypeLite peut générer Tapuscrit des interfaces à partir de C#:

http://type.litesolutions.net/

39voto

V.B. Points 1211

Web Essentials permet de compiler des fichiers C # en fichiers TypeScript .d.ts lors de la sauvegarde. Ensuite, vous pouvez référencer les définitions à partir de vos fichiers .ts .

27voto

citykid Points 1786

TypeLite et T4Ts au-dessus des deux avait l'air bien, juste pris un, TypeLite, fourche à obtenir un soutien pour

  • ValueTypes,
  • Nullable
  • camelCasing (Tapuscrit racine doc utilise des chameaux, et cela va trop bien ensemble avec le C#)
  • champs publics (l'amour propre et lisible POCOs, le rend aussi facile pour le Compilateur C#)
  • désactiver le module de génération

Ensuite, j'ai besoin de C# interfaces et de la pensée, il est temps d'écrire un simple T4 script qui fait exactement ce dont j'ai besoin. Il comprend également des Enums. Pas de pensions de titres requis, il suffit de < 100 lignes de T4.

L'utilisation de la
Pas de bibliothèque, pas de NuGet, juste cette plaine simple fichier T4 - utilisation "ajouter un élément" dans Visual Studio et choisir n'importe quel modèle T4. Puis les coller dans le fichier. S'adapter à chaque ligne avec "ACME". Pour chaque classe C# ajouter une ligne

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

L'ordre des questions, de tout type connu sera utilisé dans les interfaces suivantes. Si vous utilisez uniquement des interfaces, de l'extension de fichier peut être .d.ts, pour les énumérations, vous avez besoin d'un .ts fichier, depuis une variable est instanciée.

Personnalisation
Hack le script.

<#@ 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 ParticleKind = {");
        foreach(var val in values) 
        {
            var name = Enum.GetName(typeof(ParticleKind), val);
            sb.AppendFormat("{0}: {1},\n", name, val);
        }
        sb.AppendLine("}");
        return sb.ToString();
    }
#>

Le prochain niveau du script sera de créer l'interface de service de la MVC JsonController classe.

19voto

Christoffer Points 1473

Voici mon approche pour le résoudre. Déclarez vos classes C # avec un attribut et les fichiers .d.ts seront générés (en utilisant des transformations T4). Il y a un paquet sur nuget et la source est disponible sur github . Je travaille toujours sur le projet, mais le support est assez important.

10voto

Lukas Kabrt Points 1351

J'ai créé un petit utilitaire pouvant générer des interfaces TypeScript à partir de classes C #. Est disponible sous forme de package NuGet . Une documentation détaillée est disponible sur la page Web du projet .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X