【问题标题】:Autofac runtime parametersAutofac 运行时参数
【发布时间】:2014-10-04 21:04:11
【问题描述】:

我是 autofac 新手,希望了解将运行时值传递给构造函数的最佳实践。我已经阅读了一堆 stackoverflow 问题,但没有一个是完全充实的。我们是否应该使用委托、工厂来创建服务等。我知道传递容器并不是实现此目的的最佳方式。

在我的特定情况下,我有一个服务可以访问多个依赖项,例如日志记录、数据提供程序等。除了传递的少数服务外,我还需要捕获运行时参数,例如用户 ID、密码。 SomeService 需要用户 ID 和密码,并在 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;
    }
}

dataprovider和log在autofac中配置

builder.RegisterType<DataProviderService>().As<IDataProvider>()
builder.RegisterType<SomeLogService>().As<ILog>()

这个“SomeService”的大部分功能都需要用户名和密码才能在执行任务之前进行验证,因此认为最好在创建时传递给构造函数,但从未处理过 autofac 的运行时要求。我已经查看了Autofac - resolving runtime parameters without having to pass container around 的问题,它似乎与我需要的很接近,但需要更多关于实现此目的的最佳方法的反馈。

【问题讨论】:

  • 您能否更具体地了解SomeService 是什么以及它如何使用用户名和密码信息?这样任何人都可以为您提供一些更针对您的案例的建议。

标签: c# inversion-of-control ioc-container autofac


【解决方案1】:

AutoFac 通过Parameterized Instantiation 的概念支持使用运行时参数解析服务。

在具有特定运行时参数的服务依赖项的客户端的构造函数中,将您的依赖项声明为Func,它根据其强类型参数返回该依赖项。

例如Func&lt;string, ISomeService&gt; myService

当 AutoFac 看到 Func 时,它会创建一个委托,该委托充当创建服务的工厂方法。

来自文档:

如果在容器中注册了类型 T,Autofac 会自动 将 Func 的依赖关系解析为创建 T 实例的工厂 通过容器。

在您的依赖项的参数列表中不可能有重复的类型,就像您的问题中的ISomeService 一样。例如。 Func&lt;string, string, ISomeService&gt; 将不起作用。在这种情况下,您需要提供custom delegate factory

来自文档:

工厂适配器提供容器的实例化功能 到托管组件而不将容器本身暴露给它们。

实现此方法的一种方法是在 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)
    {
        // ..

您的 ISomeService 客户端将如下所示:

public class MyClient
{
    public MyClient(SomeService.Factory serviceFactory)
    {
        // Resolve ISomeService using factory method
        // passing runtime parameters
        _myService = serviceFactory("this", "that");
    }
}

请注意,服务的所有非运行时参数(在您的情况下为 IDataProvider 和 ILog)继续由容器自动解析。

【讨论】:

    【解决方案2】:

    一般来说你应该prevent passing runtime values into constructors。这将使您的设计和 DI 配置复杂化很多。构造函数用于依赖项和配置值。通过方法参数传递运行时值或注入允许您检索这些运行时值的服务。以IUserContext 服务为例,该服务允许检索当前登录用户的名称。

    【讨论】:

    • “配置值”通常不是“运行时值”吗?
    • 不。这些是恒定的;它们在申请过程中不会改变。
    • 只是一个极客的观点,但我不觉得这种方法会带来好的类设计。在我看来,类实现甚至不应该意识到 DI / IoC 正在发生的事实。如果该类在构建时需要一个值,我会将其设为参数;无论 Autofac 的意见/能力如何,我都会有这种感觉,但他们seem to agreeanother answer 提到的那样,Autofac 确实通过参数化实例化支持这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多