Javascript `deps:[]`也可以与`useClass`一起使用吗?
我已经知道使用什么/如何使用Javascript `deps:[]`也可以与`useClass`一起使用吗?,javascript,angular,Javascript,Angular,我已经知道使用什么/如何使用deps 当工厂方法需要注入令牌时,我们需要提供它们,如: const randomFactory = (car,engine) => { return ... }; ... providers: [Car,Engine, { provide: 'Random', useFactory: randomFactory , deps: [Car, Engine],
deps
当工厂方法需要注入令牌时,我们需要提供它们,如:
const randomFactory = (car,engine) => { return ... };
...
providers: [Car,Engine,
{ provide: 'Random',
useFactory: randomFactory ,
deps: [Car, Engine],
},
]
但我读过:
所以它基本上是deps
的,只有在使用useFactory
时才相关,对吗?->准确-仅适用于
useFactory
但后来我问:
deps可以与useClass一起使用吗?我以为它们只供工厂使用–->是的,他们可以。当您注入需要显式命名令牌的泛型依赖项时,它将非常有用 我不想在两个地方继续评论,因此我的问题是: 问题: 在哪些情况下,我会将
useClass
与deps
一起使用
此外,即使我使用了它,也可以说classFoo
:
Class Foo
{
constructor ( private s1:Service1 , private s2:service2){}
}
^它已经有了自己的ctor。deps依赖项将注入到哪里?(附于附件一)
}
请举一个场景+代码的例子。
deps
仅在中提供,而不在中提供
这是因为Angular团队为DI注释选择的方法(发出的类型元数据)只适用于类构造函数。而useFactory
提供程序中使用的常规函数不能使用类型元数据,需要替代的注释方法,即dep
数组
如中所述,可以使用
参数
静态属性为DI注释类。类提供程序参数
和工厂提供程序deps
都接受由提供程序令牌或装饰程序实例数组组成的数组(如[new Optional(),new Inject(…)]
。有两种提供程序:
静态提供者和提供者
静态提供者
它是一种用于以静态方式配置注入器的提供程序(无反射)
根据
platformXXXX()不再接受依赖于反射的提供程序。
具体来说,方法签名从提供者[]到
静态提供程序[]
这是什么意思?
1) 当我们将提供者传递给平台时,我们必须指定deps
,因为我们必须使用StaticClassProvider
或ConstructorProvider
,而不仅仅是ClassProvider
(见上图)
供应商
在@NgModule或@Component/@Directive元数据中写入提供程序时,我们通常使用这种提供程序
看看这个答案,我想说这里不需要deps
。我们只需要在providers数组中提供Params
,angular将为我们完成所有工作
@埃斯特斯说 DEP仅在useFactory提供程序中可用,但在useClass中不可用 提供者 因为他指的是
Provider
(更准确地说是ClassProvider
)而不是StaticProvider
p.S.您也可以阅读我关于
StaticInjector
:)的文章
是,
deps
可由useFactory
或useClass
使用
你可以通过观察角光源(5+)来了解这一点。如果为useClass
或useFactory
填充deps
,则将在提供程序元数据中返回deps
:
getProviderMetadata(provider: cpl.ProviderMeta): cpl.CompileProviderMetadata {
let compileDeps: cpl.CompileDiDependencyMetadata[] = undefined !;
let compileTypeMetadata: cpl.CompileTypeMetadata = null !;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null !;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) {
compileTypeMetadata = this._getInjectableMetadata(provider.useClass, provider.dependencies);
compileDeps = compileTypeMetadata.diDeps; <-- ***HERE***
if (provider.token === provider.useClass) {
// use the compileTypeMetadata as it contains information about lifecycleHooks...
token = {identifier: compileTypeMetadata};
}
} else if (provider.useFactory) {
compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies);
compileDeps = compileFactoryMetadata.diDeps; <-- ***HERE***
}
return {
token: token,
useClass: compileTypeMetadata,
useValue: provider.useValue,
useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : undefined,
deps: compileDeps, <-- ***HERE ***
multi: provider.multi
};
}
对于单个提供者()也是如此
也就是说,在典型情况下,通常不需要在deps
数组中使用useClass
提供程序并显式命名依赖项。您应该让DI隐式地为您处理这个问题
当我试图实现这些问题所引用的静态
forRoot
方法时,我发现了一些模糊的用例。如果我理解正确,我应该在演示中看到deps。但是我没有找到它。(它显示一个错误)您应该添加,deps:[MyParams]
以使其工作。我刚刚展示了在注入器的情况下它是必需的。创建这是一个固定版本。您知道这在实践中应该如何工作吗。到目前为止,我还没有调查清楚为什么dep
包含在您发布的源代码中。但由于ClassProvider接口没有DEP,这意味着在某种程度上它是不受支持的(据我所知,从来没有)。似乎对DEP
的支持是有意的(基于源代码),如果您选择将它们一起使用,它确实起作用。至于将来它是否会被弃用,我不能说。。。我同意,在类提供程序接口中没有deps
似乎表明它可能不是预期的用例。没有技术原因说明deps
不适用于这两者,因为实现非常类似。在这种情况下,Angular选择为useClass
提供程序支持deps
,并为开发人员提供选择是否使用它的灵活性。也许应该解决框架设计中的这种不一致性(有人想将其提交给核心团队吗?)。正如我所发现的(我猜这在另一个提到StaticInjector的回答中提到过),deps
只能作为类使用,即它可以与AOT一起使用,但不能与JIT一起使用。这可能就是为什么它在plunker中不起作用的原因。同意-这是不协调的。它适用于AOT,但在JIT中被忽略。
export const MyParams = new InjectionToken<string[]>('params');
export class MyService {
constructor(@Inject(MyParams) public someParameters: string[]) {}
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular ' + VERSION.full;
constructor() {
const inj = Injector.create([
{ provide: MyService, useClass: MyService } <=== we will get an error because we have to define deps
])
}
}
getProviderMetadata(provider: cpl.ProviderMeta): cpl.CompileProviderMetadata {
let compileDeps: cpl.CompileDiDependencyMetadata[] = undefined !;
let compileTypeMetadata: cpl.CompileTypeMetadata = null !;
let compileFactoryMetadata: cpl.CompileFactoryMetadata = null !;
let token: cpl.CompileTokenMetadata = this._getTokenMetadata(provider.token);
if (provider.useClass) {
compileTypeMetadata = this._getInjectableMetadata(provider.useClass, provider.dependencies);
compileDeps = compileTypeMetadata.diDeps; <-- ***HERE***
if (provider.token === provider.useClass) {
// use the compileTypeMetadata as it contains information about lifecycleHooks...
token = {identifier: compileTypeMetadata};
}
} else if (provider.useFactory) {
compileFactoryMetadata = this._getFactoryMetadata(provider.useFactory, provider.dependencies);
compileDeps = compileFactoryMetadata.diDeps; <-- ***HERE***
}
return {
token: token,
useClass: compileTypeMetadata,
useValue: provider.useValue,
useFactory: compileFactoryMetadata,
useExisting: provider.useExisting ? this._getTokenMetadata(provider.useExisting) : undefined,
deps: compileDeps, <-- ***HERE ***
multi: provider.multi
};
}
if (provider.useClass) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useClass.diDeps);
expr = ctx.importExpr(provider.useClass.reference).instantiate(depExprs); <-- ***HERE***
} else if (provider.useFactory) {
const depExprs = convertDeps(providerIndex, provider.deps || provider.useFactory.diDeps);
expr = ctx.importExpr(provider.useFactory.reference).callFn(depExprs);<-- ***HERE***
}
if (providerMeta.useClass) {
providerExpr = ctx.importExpr(providerMeta.useClass.reference);
flags |= NodeFlags.TypeClassProvider;
deps = providerMeta.deps || providerMeta.useClass.diDeps; <-- ***HERE***
} else if (providerMeta.useFactory) {
providerExpr = ctx.importExpr(providerMeta.useFactory.reference);
flags |= NodeFlags.TypeFactoryProvider;
deps = providerMeta.deps || providerMeta.useFactory.diDeps; <-- ***HERE***
}
} else if (providerMeta.useExisting) {
providerExpr = o.NULL_EXPR;
flags |= NodeFlags.TypeUseExistingProvider;
deps = [{token: providerMeta.useExisting}];
} else {
providerExpr = convertValueToOutputAst(ctx, providerMeta.useValue);
flags |= NodeFlags.TypeValueProvider;
deps = [];
}