如何在具有角度注入参数的打字稿中创建新对象

ibe*_*beu 4 dependency-injection inject angularjs typescript

我有一个打字稿类,其中构造函数有一个普通参数和一个角度注入参数:

export class MyClass {
    private translation:string;

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

如果我现在想创建一个对象,我该怎么做呢?

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
Run Code Online (Sandbox Code Playgroud)

即使我写了$filter?它也不会工作,因为它无法识别范围并且它将是未定义的。

那么,我怎样才能让它发挥作用呢?

我的方法

假设我在另一个类中,我想在其中创建 MyClass 的对象。以下代码可以工作,但我不喜欢在此类中也注入 $filter 的想法,因为它不需要它。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我宁愿调用类似的东西var clazz = new MyClass('myName');$filter自动注入 MyClass 中的依赖项。这有可能吗?

Igo*_*gor 5

我认为你错过了一些关于 DI(注入)的事情。重点是不要手动创建任何依赖项。相反,始终解决它们,而对于 Angular,这是在构造函数中自动完成的。唯一的例外应该是具有 0 角度依赖关系的类,并且仅限于没有像纯实体/数据类那样的行为。

Typescript 还使您能够定义接口(契约)。您应该创建它们并使用它们作为参考点,而不是直接使用您的类类型。这将允许您更改行为甚至定义(提供松散耦合)。这也使得单元测试变得更加容易。

您的示例可以像这样重写:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在使用MyClass名称注册 Angular ngMyService,并使用 Angular 注册 ClassUsingTheOtherClass。注册它们的位置取决于它们的用途(控制器、服务、工厂、过滤器等)。

当 Angular 创建实例时,ClassUsingTheOtherClass它会自动MyClass注入到构造函数中。MyClass反过来会自动$filter注入到构造函数中。

最后我发现字符串name参数没有任何用途MyClass,所以我将其删除。您将永远无法注入它,因为您无法注册带有要注入的角度的字符串。您可以在类型本身中对名称进行硬编码,或者提供name可由用户设置的属性/字段MyClass(将字段添加到接口中IMyService),但这在我看来打破了高内聚规则。