angularjs - TypeLite-generering med tillägg av hierarkiskt beroende


Jag använder för närvarande en klientversion med AngularJS 1.x i TypeScript och en AspNet WebApi-backend i C#.

För kommunikation med backend använder jag $resource-tjänsten från Angular. Genom att använda denna tjänst måste mina modellgränssnitt som genereras med TypeLITE utvidga

ng.resource.IResource<IModel> 

Är det möjligt att automatiskt utöka alla genererade modellgränssnitt från detta gränssnitt som beskrivs av Angular?

Annars måste allt göras separat på det här sättet

export interface Model extends ng.resource.IResource<Model> {
}

Stort tack på förhand, MacX

Svar #1

Detta är inte en enkel uppgift. Ett alternativ är att skapa en anpassad TsModelVisitor som lägger till en dummyklass ng.resource.IResource<T> i kodmodellen och ändrar basklassen för alla andra klasser i kodmodellen.

Jag skulle försöka följande steg:

  • skapa en klass som härstammar från TsModelVisitor

    • i VisitModel-metoden skapa en ny TsClass-modell som representerar Angular-modellgränssnittet
    • i VisitClass-metoden, sätt BaseType till den klass som skapades i VisitModel-metoden för varje klass
  • anropa din modellbesökare i .tt-fil

    var ts = TypeScript.Definitions()
                 .AsConstEnums(false);
    var model = ts.ModelBuilder.Build();
    model.RunVisitor(new YourModelVisitor());
    
  • istället för <#= ts.Generate(TsGeneratorOutput.Properties) #> använd '<#= ts.ScriptGenerator.Generate(model, TsGeneratorOutput.Properties) #>' för att generera utdata

Svar #2

Det enklaste sättet att uppnå detta är att utöka TsGenerator. Skapa en fil med namnet TsAngularJsModelGenerator.ttinclude i samma katalog som din TypeLite.Net4.tt-fil och klistra in följande:

<#@ assembly name="$(TargetDir)\TypeLite.dll" #>
<#@ assembly name="$(TargetDir)\TypeLite.Net4.dll"#>

<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="TypeLite" #> 
<#@ import namespace="TypeLite.TsModels" #> 

<#+
class TsAngularJsModelGenerator : TsGenerator
{
    protected override void AppendClassDefinition(TsClass classModel, ScriptBuilder sb, TsGeneratorOutput generatorOutput)
    {

        string typeName = this.GetTypeName(classModel);
        string visibility = this.GetTypeVisibility(classModel, typeName) ? "export " : "";
        sb.AppendFormatIndented("{0}interface {1}", visibility, typeName);
        if (classModel.BaseType != null)
        {
            sb.AppendFormat(" extends {0}", this.GetFullyQualifiedTypeName(classModel.BaseType));
        }
        else
        {
            sb.AppendFormat("  extends ng.resource.IResource<{0}>", typeName);
        }
        sb.AppendLine(" {");
        var members = new List<TsProperty>();
        if ((generatorOutput & TsGeneratorOutput.Properties) == TsGeneratorOutput.Properties)
            members.AddRange(classModel.Properties);
        if ((generatorOutput & TsGeneratorOutput.Fields) == TsGeneratorOutput.Fields)
            members.AddRange(classModel.Fields);
        using (sb.IncreaseIndentation())
        {
            foreach (var property in members)
            {
                if (property.IsIgnored)
                    continue;
                var propTypeName = this.GetPropertyType(property);
                sb.AppendLineIndented(string.Format("{0}: {1};", this.GetPropertyName(property), propTypeName));
            }
        }
        sb.AppendLineIndented("}");
        _generatedClasses.Add(classModel);
    }
} #>

Observera: Du kommer förmodligen att behöva ändra de första två raderna så att de pekar på en giltig plats för dig (jag upptäckte att under MVC innehåller inte alltid bin-katalogen TypeLite.dll och TypeLite.Net4.dll-filerna - om du stöter på problem, kom ihåg att sätta värdet på debug till true på den första raden i TypeLite.Net4.tt-filen för att få bättre diagnostik).

Lägg sedan till följande rad i din TypeLite.Net4.tt-fil under raden <#@include file="Manager.ttinclude"#>:

<#@include file="TsAngularJsModelGenerator.ttinclude"#>

Slutligen, i filen TypeLite.Net4.tt ändra anropet till TypeScript.Definitions och skicka en ny instans av TsAngularJsModelGenerator som följer:

<# var ts = TypeScript.Definitions(new TsAngularJsModelGenerator())
    .WithReference("Enums.ts")
    .ForLoadedAssemblies();
#>