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

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

问题描述

我需要能够将连接字符串传递到某些服务实现中。我在构造函数中执行此操作。用户可以配置该连接字符串,然后将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实现:

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'.

在这里我有什么选择?

What are my options here?

推荐答案

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

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


  1. 工厂方法

  1. factory method

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

并将工厂方法注入服务中,而不是 INestedService

and inject the factory method in 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
    }
}


  • 工厂类

  • factory class

    public class RootServiceFactory : IRootServiceFactory 
    {
        // in case you need other dependencies, that can be resolved by DI
        private readonly IServiceCollection services;
    
        public RootServiceCollection(IServiceCollection services)
        {
            this.services = services;
        }
    
        public CreateInstance(string connectionString) 
        {
            // instantiate service that needs runtime parameter
            var nestedService = new NestedService(connectionString);
    
            // resolve another service that doesn't need runtime parameter
            var otherDependency = services.GetService<IOtherService>()
    
            // pass both into the RootService constructor and return it
            return new RootService(otherDependency, nestedDependency);
        }
    }
    

    并注入 IRootServiceFactory ,而不是您的 IRootService

    and inject IRootServiceFactory instead of your IRootService.

    IRootService rootService = rootServiceFactory.CreateIntsance(connectionString);
    


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

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