【问题标题】:Create multiple instances of same dependency w/ different configuration创建具有不同配置的相同依赖项的多个实例
【发布时间】:2019-01-12 00:30:21
【问题描述】:

我有一个应用程序 (IJobInit),它使用 JSON 设置中的列表来创建类的多个实例 (IJob)。这个类使用另外两个依赖项IInputClientIOutputClient 来完成一些工作。它使用 M.Extensions.DependencyInjection 创建一个容器,然后交给 AutoFac 创建一个 IContainer。

IJobInit(IContainer container)

我希望为每个 IJob 实例配置不同的 IInputClient。特别是,我想传递一个秘密供它使用。结果是:

IInputClient(HttpClient client)

其中 HttpClient 是使用 ConfigureHttpClient 配置的,因此 IJob 不知道它已经过预身份验证。这也很合适:

IInputClient(ISecretProvider secretsProvider, string secretName)

最终结果是三个 IJob 实例,IInputClient 配置不同。

IJob(IInputClient inputClient1, IOutputClient outputClient)
IJob(IInputClient inputClient2, IOutputClient outputClient)
IJob(IInputClient inputClient3, IOutputClient outputClient)

我如何实现这一目标?我正在查看 Autofac 范围,但这些控制何时创建实例而对其配置没有任何控制(除非我错过了它)。

一位同事建议我可以使用自己的配置在其自己的进程中托管每个 IJob 实例,这可能的,但我试图在单个 Azure 函数中托管所有作业并使用在配置中列出以创建内部作业。

谢谢!

【问题讨论】:

  • 听起来你已经反转了导致问题的控制。如果您有一个可枚举的配置,那么根据配置的数量创建您的可枚举IJobInit/IJob。 Autofac 支持Enumerated relationships implicitly
  • 另外看起来你有多个容器......这些类型的配置真的很少见,我不明白为什么你的实现需要这样做。在第二次检查时,您可能需要为您的 IInputClient 创建另一个抽象层,将 HttpClient 替换为一个知道秘密实现的对象,尽管您可以使用 pre-configuring named instances 但我不确定这是否能满足您的需求.
  • 我喜欢列举的关系。我想我也可以使用 Autofac 的提供程序以编程方式注册它们。

标签: c# .net-core azure-functions autofac


【解决方案1】:

我对这个解决方案并不完全满意,但它现在有效。

        private async Task<IInputClient> GetClientAsync(string secretId)
        {
            HttpClient httpClient = this.httpClientFactory.CreateClient();

            string secret = await this.secretsProvider.GetSecretAsync(secretId);
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Concat(":", secret))));

            return this.scope.Resolve<IInputClient>(new TypedParameter(typeof(HttpClient), httpClient));
        }

【讨论】:

  • 为什么不使用IInputClient 作为该方法所在类的依赖项?
  • 我愿意。我使用在这种方法中创建的客户端来创建IProcessor(IInputClient, IOutputClient) 的列表,然后运行它们。 IInputClient client = await this.GetClientAsync(this.GetKeyVaultSecretUri(kvp.Key)); var proc = this.scope.Resolve&lt;Processor&gt;(new NamedParameter("inputClient", client));
  • 您继续使用 Resolve。使用依赖注入,您应该很少需要手动解决任何问题......
  • 我不反对。文档描述了一个IRegistrationSource,它几乎可以满足我的需要,但它会在我想要的地方返回A、B、C A、A'、A''、A'''等等。跨度>
  • 我想如果我可以在容器构建之前(或之后)动态地将实例注册到容器,我可以使用枚举器功能来简化。编辑:也许 RegistrationSource 可以做到这一点,尽管我仍然需要在激活器中调用 resolve。我需要做更多的研究和实验。 (对这一切仍然相对较新!)
猜你喜欢
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
相关资源
最近更新 更多