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
一起使用

此外,即使我使用了它,也可以说class
Foo

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 = [];
    }