如何将运行时参数作为依赖项解析的一部分传递? [英] 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 实现:
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:
工厂类(类似于
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屋!