2016-03-31 4 views
2

ich ein Typoskript Klasse schaffen, in dem Konstruktor ich eine normale und eine Winkel injizierten Argument:Wie neues Objekt in Typoskript mit Winkel injizierten Parameter

export class MyClass { 
    private translation:string; 

    public static $inject = ['$filter']; 
    constructor(name:string, $filter: ng.IFilterService) { 
     this.translation = filter('translate')('code').toString(); 
    } 
} 

Wenn ich jetzt ein Objekt erstellen möchten , wie kann ich es tun?

new MyClass('myname'); //won't compile because there are too few parameters 
new MyClass('myname', filter); //makes no sense since I want to inject it 

Auch wenn ich schrieb $filter? es wird nicht funktionieren, weil sie den Umfang nicht erkennen, und es wird nicht definiert sein.

Also, wie kann ich das zum Funktionieren bringen?

Mein Ansatz

Lassen Sie sich sagen, dass ich in einer anderen Klasse bin, in dem ich ein Objekt von MyClass erstellen möge. Der folgende Code wird funktionieren, aber ich mag die Idee nicht, $ filter auch in dieser Klasse zu injizieren, da er sie nicht benötigt.

export class ClassUsingTheOtherClass { 
    private filter:ng.IFilterService; 

    public static $inject = ['$filter']; 
    constructor($filter: ng.IFilterService) { 
     this.filter = $filter; 
    } 

    doThings() { 
     var clazz = new MyClass('myName', this.filter); 
    } 
} 

Ich würde eher so etwas wie diese var clazz = new MyClass('myName'); nennen und mit $filter automatisch als Abhängigkeit in MyClass injiziert. Ist das überhaupt möglich?

+0

Wann würden Sie diese 'neue MyClass ('myname') nennen?' '? Es scheint, als würde es nie aufgerufen werden, weil Sie eine 'filter'-Instanz benötigen, andernfalls wird die Klasse eventuell auf einen undefinierten Fehler stoßen. Was ist der Zweck von 'myname' Parameter? Wie könnte das jemals injiziert werden? Diese Definition würde mit Angular nicht funktionieren. – Igor

+0

Ich schrieb die Frage um. Schau mal. myname ist nur die Zeichenfolge, die mit dem angular-translate-Filter übersetzt wird. Und ich möchte nicht, dass es eingespritzt wird, weil ich es weitergeben will, wenn ich es übersetzen muss. – iberbeu

Antwort

4

Ich denke, Sie vermissen etwas über DI (Injektion). Der Punkt ist, keine Abhängigkeiten manuell zu erstellen. Stattdessen lösen Sie sie immer und mit Angular geschieht dies automatisch im Konstruktor. Die einzigen Ausnahmen sollten Klassen sein, die 0 Winkelabhängigkeiten haben und auf kein Verhalten wie eine reine Entity/Datenklasse beschränkt sind.

Auch Typescript bietet Ihnen die Möglichkeit, Schnittstellen (Verträge) zu definieren. Sie sollten sie erstellen und diese als Referenzpunkte anstelle Ihrer Klassentypen direkt verwenden. Auf diese Weise können Sie das Verhalten oder sogar Definitionen ändern (bietet eine lose Kopplung). Dies erleichtert auch das Testen von Einheiten.

Ihr Beispiel rewriten wie so könnte:

export interface IMyService{ 
    doThing:()=>void; 
} 

// should be registered with angular with service name 'ngMyService' 
export class MyClass implements IMyService { 
    private translation:string; 

    public static $inject = ['$filter']; 
    constructor($filter: ng.IFilterService) { 
     this.translation = $filter('translate')('code').toString(); 
    } 

    doThing() : void { 
     // something 
    } 
} 

export class ClassUsingTheOtherClass { 

    public static $inject = ['ngMyService']; 
    constructor(private myService: IMyService) { 
    } 

    doThings() { 
     this.myService.doThing(); 
    } 
} 

Jetzt MyClass mit Winkel mit dem Namen als auch ngMyService und registrieren ClassUsingTheOtherClass mit Winkeln registrieren. Wo Sie sie registrieren, hängt von ihrer Verwendung ab (Controller, Service, Fabrik, Filter usw.).

Wenn eckig eine Instanz von ClassUsingTheOtherClass erstellt, wird automatisch MyClass in den Konstruktor eingefügt. MyClass wiederum wird automatisch in den Konstruktor $filter injiziert.

Schließlich sehe ich keine Bedeutung für die Zeichenfolge name Parameter in MyClass, also habe ich es entfernt. Sie können dies niemals injizieren, da Sie keine Zeichenfolge mit eckigen Klammern registrieren können, um injiziert zu werden.Sie könnten entweder den Namen im Typ selbst fest codieren ODER eine name Eigenschaft/Feld, die vom Benutzer MyClass gesetzt werden könnte (fügen Sie das Feld der Schnittstelle IMyService), aber dies bricht die hohe Kohäsion Regel meiner Meinung nach.

+1

Ich mag es. Das Problem war nicht wirklich ein allgemeines Missverständnis von DI, sondern dass ich angular nicht so gebrauche, wie ich sollte. Ich versuchte irgendwie zu vermeiden, jedes einzelne Ding eckig zu registrieren, aber jetzt sehe ich, dass es der richtige Weg ist. Wie auch immer, ich denke, das ist etwas, das in Typoskript verbessert werden konnte – iberbeu

+1

Gute Antwort. So viel Fokus auf das Warum wie das Wie –

+0

@IBEBEU - (* Korrektur, ich meinte, gut zu schreiben nicht Gott *) - Gutes Geschäft! Es hat mich auch ein bisschen gebraucht, als ich anfing, mit Angular und Typescript zu arbeiten (ich habe sie beide zur selben Zeit ausgewählt). Sobald Sie jedoch den Dreh raus haben (Abhängigkeiten über Schnittstellen definieren und Winkelregistrierung verwenden), wird es zu etwas, an das Sie fast gar nicht mehr denken müssen (2. Natur). – Igor

-2
export class MyClass { 

    public static $inject = ['$scope']; 
    constructor(name:string, $scope?: ng.IScope) { 
     //do things...     
    } 
} 

Durch Ihre Klasse modden, so gibt es ein Fragezeichen hinter $scope ist, sagen Sie dem Compiler, dass die $scope ein optionaler Parameter ist.

Jetzt können Sie einfach new MyClass('myname'); ausführen.

+0

Hast du das versucht? Es kompiliert, wie ich bereits in meiner Frage gesagt habe, aber der Umfang wird undefiniert sein – iberbeu

+1

Ich habe deine Frage falsch gelesen, ich dachte, es wäre ein Problem zu kompilieren. Ich versuche, Ihre Frage zu verstehen, aber ich kann nicht wirklich wissen, warum Sie einen Bereich in einer generischen Klasse injizieren möchten. Wenn es einen $ scope benötigt, sollten Sie jeder Klasse einen eigenen $ scope geben, der vom $ scope der Klasse, in der Sie die neuen Instanzen generieren, erbt. 'neue MyClass ('myname', scope. $ Neu (falsch));' – Pjetr

+0

Um Umfang zu schreiben war eine schlechte Idee. Was ich wirklich brauche ist $ filter, um eine Sache zu übersetzen. Ich habe meine Frage umgeschrieben. Gibt es einen anderen Weg, dies zu tun? Mißverstände ich die Dinge hier? – iberbeu

Verwandte Themen