如何将运行时参数作为依赖项解析的一部分传递? [英] How can I pass a runtime parameter as part of the dependency resolution?

查看:18
本文介绍了如何将运行时参数作为依赖项解析的一部分传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要能够将连接字符串传递到我的某些服务实现中.我在构造函数中这样做.连接字符串可由用户配置,将添加 ClaimsPrincipal 作为 Claim.

I need to be able to pass a connection string into some of my service implementations. I am doing this in the constructor. The connection string is configurable by user will be added the ClaimsPrincipal as a Claim.

到目前为止一切正常.

不幸的是,我也希望能够充分利用 ASP.NET Core 中的依赖注入功能,并通过 DI 解决服务实现.

Unfortunately, I also want to be able to use the dependency injection features in ASP.NET Core to the fullest and resolve the service implementation though DI.

我有一个 POC 实现:

I have a POC implmentation:

public interface IRootService
{
    INestedService NestedService { get; set; }

    void DoSomething();
}

public class RootService : IRootService
{
    public INestedService NestedService { get; set; }

    public RootService(INestedService nestedService)
    {
        NestedService = nestedService;
    }

    public void DoSomething()
    {
        // implement
    }
}


public interface INestedService
{
    string ConnectionString { get; set; }

    void DoSomethingElse();
}

public class NestedService : INestedService
{
    public string ConnectionString { get; set; }

    public NestedService(string connectionString)
    {
        ConnectionString = connectionString;
    }

    public void DoSomethingElse()
    {
        // implement
    }
}

这些服务已在启动时注册,并且INestedService 已添加到控制器的构造函数中.

These services have been registered during startup and INestedService has been added the constructor of a controller.

public HomeController(INestedService nestedService)
{
    NestedService = nestedService;
}

正如预期的那样,我在尝试激活Test.Dependency.Services.NestedService"时收到错误无法解析System.String"类型的服务.

As expected, I get the error Unable to resolve service for type 'System.String' while attempting to activate 'Test.Dependency.Services.NestedService'.

我有哪些选择?

推荐答案

要传递在应用程序启动时未知的运行时参数,您必须使用工厂模式.您有两个选择:

To pass a runtime parameter not known at the start of the application, you have to use the factory pattern. You have two options here:

  1. 工厂类(类似于IHttpClientFactory的实现方式)

 public class RootService : IRootService
 {
     public RootService(INestedService nested, IOtherService other)
     {
         // ...
     }
 }

 public class RootServiceFactory : IRootServiceFactory 
 {
     // in case you need other dependencies, that can be resolved by DI
     private readonly IServiceProvider services;

     public RootServiceFactory(IServiceProvider services)
     {
         this.services = services;
     }

     public IRootService CreateInstance(string connectionString) 
     {
         // instantiate service that needs runtime parameter
         var nestedService = new NestedService(connectionString);

         // note that in this example, RootService also has a dependency on
         // IOtherService - ActivatorUtilities.CreateInstance will automagically
         // resolve that dependency, and any others not explicitly provided, from
         // the specified IServiceProvider
         return ActivatorUtilities.CreateInstance<RootService>(services,
             new object[] { nestedService, });
     }
 }

并注入 IRootServiceFactory 而不是你的 IRootService

and inject IRootServiceFactory instead of your IRootService

 IRootService rootService = rootServiceFactory.CreateInstance(connectionString);

  • 工厂方法

  • factory method

     services.AddTransient<Func<string,INestedService>>((provider) => 
     {
         return new Func<string,INestedService>( 
             (connectionString) => new NestedService(connectionString)
         );
     });
    

    并将工厂方法注入您的服务而不是 INestedService

    and inject the factory method into your service instead of INestedService

     public class RootService : IRootService
     {
         public INestedService NestedService { get; set; }
    
         public RootService(Func<string,INestedService> nestedServiceFactory)
         {
             NestedService = nestedServiceFactory("ConnectionStringHere");
         }
    
         public void DoSomething()
         {
             // implement
         }
     }
    

    或每次调用解决

     public class RootService : IRootService
     {
         public Func<string,INestedService> NestedServiceFactory { get; set; }
    
         public RootService(Func<string,INestedService> nestedServiceFactory)
         {
             NestedServiceFactory = nestedServiceFactory;
         }
    
         public void DoSomething(string connectionString)
         {
             var nestedService = nestedServiceFactory(connectionString);
    
             // implement
         }
     }
    

  • 这篇关于如何将运行时参数作为依赖项解析的一部分传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆