工厂提供商可以选择依赖吗?

时间:2016-09-01 18:54:09

标签: angular typescript dependency-injection

例如:

@NgModule ({
  providers: [ 
    { provide: MyService, 
      useFactory: (optionalDep) => new MyService(optionalDep)
      deps: [SOME_DEP]
    }
})
class MyModule {}

useFactory 是否有可选的依赖项?

5 个答案:

答案 0 :(得分:10)

根据官方文件,您可以执行以下操作:

const Location = new InjectionToken('location');
const Hash = new InjectionToken('hash');

const injector = Injector.create([{
  provide: Hash,
  useFactory: (location: string) => `Hash for: ${location}`,
  // use a nested array to define metadata for dependencies.
  deps: [[new Optional(), Location]]
}]);

expect(injector.get(Hash)).toEqual('Hash for: null');

有关详情,请参阅https://angular.io/api/core/FactoryProvider#example

答案 1 :(得分:5)

我找到了这样的解决方法:

class OptionalDepHolder {
  constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
}

@NgModule ({
  providers: [ 
    { provide: MyService, 
      useFactory: (holder) => new MyService(holder.optionalDep)
      deps: [OptionalDepHolder]
    }
})
class MyModule {}

答案 2 :(得分:0)

工厂接受一个功能。

typescript中的装饰器可以应用于:类声明,方法,访问器,属性或参数。

换句话说,目前你只能装饰一个班级和班级成员。

  

参数是指方法的参数,而不是函数。

因此,由于您无法在函数中修饰函数和更多参数,因此您无法设置@Optional标记。

此语言/规范限制可能在将来发生变化。

另一件需要注意的事情是,typescript支持的元数据功能和使用 reflect-metadata 的angular使用的元数据功能旨在用于类。这当然是无稽之谈,类是函数......但这是一般的心理模型。

根据文档,deps数组接受提供者令牌,这意味着您无法提示可选的依赖关系。

在工厂中支持可选的依赖项是个好主意。您应该通过功能请求打开GH问题!

答案 3 :(得分:0)

确实可以为工厂提供者声明可选的依赖项。

using (var repo = new Repository("/Users/sushi/code/redux/playscript"))
{
    var commitLog = repo.Commits.QueryBy(new CommitFilter() { FirstParentOnly = true, IncludeReachableFrom = "master" });
    foreach (var commit in commitLog)
    {
        Console.WriteLine($"{commit.Sha}");
        Console.ReadKey();
    }
}

然后,在您的提供者列表中,使用值提供者提供默认值

export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
export const myOptionalServiceParameterDefault = 42;

该服务将使用提供的参数默认值(可以是@NgModule({ providers: [ { provide: MY_OPTIONAL_SERVICE_PARAMETER, useValue: myOptionalServiceParameterDefault }, { provide: MyService, useFactory: (optionalParam) => new MyService(optionalParam) deps: [MY_OPTIONAL_SERVICE_PARAMETER] } }) export class Module {} ),,除非消费者在提供商列表中稍后覆盖该值。

undefined中的HttpModule使用此模式为其服务提供可选的依赖项@angular/http

答案 4 :(得分:0)

所以我一直在尝试解决它。检查一下:

@NgModule ({
  providers: [ 
    { provide: MyService, 
      useFactory: (optionalDep) => new MyService(optionalDep)
      deps: [[new Optional(), new Inject(SOME_DEP)]]
    }
})
class MyModule {}