如何传递运行时参数作为依赖关系解决方案的一部分? [英] How can I pass a runtime parameter as part of the dependency resolution?
问题描述
我需要能够将连接字符串传递到某些服务实现中。我在构造函数中执行此操作。用户可以配置该连接字符串,然后将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
-
工厂方法
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屋!