mag*_*guy 6 c# ioc-container inversion-of-control autofac
我是autofac的新手,希望看到将运行时值传递给构造函数的最佳实践.我已经阅读了一堆stackoverflow问题,但是没有一个完全充实.我们应该使用代表,工厂来创建服务等.我知道传递容器并不是实现这一目标的最佳方法.
在我的特定情况下,我有一个访问多个依赖项的服务,比如日志记录,数据提供者等.除了传递的少量服务之外,我还需要捕获运行时参数,比如userid,password.SomeService需要用户标识和密码,并在Web查看器执行特定操作时查找.以下是我的问题,并强调了问题.
public class SomeService : ISomeService
{
private readonly IDataProvider _dataProvider;
private readonly ILog _log;
private readonly string _username;
private readonly string _password;
public SomeService(IDataProvider dataProvider, ILog log,
string username, string password)
{
_dataProvider = dataProvider;
_log = log;
_username = username;
_password = password;
}
}
Run Code Online (Sandbox Code Playgroud)
数据提供者和日志在autofac中配置
builder.RegisterType<DataProviderService>().As<IDataProvider>()
builder.RegisterType<SomeLogService>().As<ILog>()
Run Code Online (Sandbox Code Playgroud)
这个"SomeService"的大多数功能都需要用户名和密码才能在执行任务之前进行验证,因此最好在创建时传递给构造函数,但从未处理过autofac的运行时要求.我已经回顾了Autofac这个问题- 解决运行时参数而不必传递容器,它似乎接近我需要的东西,但需要更多关于完成此任务的最佳方法的反馈.
通常,您应该防止将运行时值传递给构造函数。这将使您的设计和 DI 配置复杂化很多。构造函数用于依赖项和配置值。通过方法参数传递运行时值或注入允许您检索这些运行时值的服务。以IUserContext允许检索当前登录用户的名称的服务为例。
AutoFac通过参数化实例化的概念支持使用运行时参数解析服务.
在具有特定运行时参数的服务的依赖关系的客户端的构造函数中,将依赖关系声明为Func根据其强类型参数返回该依赖关系.
例如 Func<string, ISomeService> myService
当AutoFac看到Func它创建一个委托时,它充当创建服务的工厂方法.
从文档:
如果在容器中注册了类型T,则Autofac将自动解析对Func的依赖关系,作为通过容器创建T实例的工厂.
在您的依赖项的参数列表中不可能有重复的类型,就像ISomeService您的问题中的情况一样.例如Func<string, string, ISomeService>不会工作.在这种情况下,您需要提供自定义委托工厂.
从文档:
工厂适配器为托管组件提供容器的实例化功能,而不会将容器本身暴露给它们.
实现此方法的一种方法是声明委托类型以及AutoFac将用作工厂方法的类型定义.
例如
public class SomeService : ISomeService
{
// Factory method
public delegate SomeService Factory(string userName, string password);
public SomeService(IDataProvider dataProvider,
ILog log,
string username,
string password)
{
// ..
Run Code Online (Sandbox Code Playgroud)
您的ISomeService客户端将如下所示:
public class MyClient
{
public MyClient(SomeService.Factory serviceFactory)
{
// Resolve ISomeService using factory method
// passing runtime parameters
_myService = serviceFactory("this", "that");
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,容器将继续自动解析服务的所有非运行时参数(在您的情况下为IDataProvider和ILog).