【问题标题】:Autofac in web applications, where should I store the container for easy access?Web应用程序中的Autofac,我应该将容器存储在哪里以便于访问?
【发布时间】:2009-03-13 21:50:07
【问题描述】:

我对使用 Autofac 还是很陌生,我在文档和示例中错过的一件事是如何轻松地从 Web 应用程序的不同位置访问已配置的容器。

我知道我可以使用 Autofac 控制器工厂来自动解析控制器的构造函数注入依赖项,但是您可能需要解决尚未注入的其他内容呢。

是否存在我不知道的明显模式?

谢谢!

【问题讨论】:

  • 顺便说一句,这个问题是在 MVC 版本 2 时被问到的。在 MVC 3 中,DependencyResolver.Current 是您所需要的,无论您使用的是 Autofac 还是其他东西。

标签: asp.net dependency-injection inversion-of-control autofac


【解决方案1】:

Autofac 的“方式”是有一个IContext 构造函数参数。 Autofac 将注入一个可用于解析类型的对象。

上下文通常是幕后的容器,IContainer 实现了IContext 接口,尽管IContext 仅限于做解析。

我知道容器不应该被“过度使用”,但作为 OP,我有需要解析提前不知道的类型的类(因此不能用作构造函数参数)。我发现在这些情况下很有用,将容器视为可用于解析其他服务的另一个服务,并像任何其他服务一样注入它。

如果您觉得使用 IContext 会将您绑定到 Autofac,并且您需要使用自己的接口对其进行抽象,那么只需在您的容器中注册一个 IContext 包装类即可。

更新:在 Autofac 2 中,IContext 被称为 IComponentContext

【讨论】:

  • 为什么不注入工厂呢?
  • @TrueWill - ...区别是什么?
  • 再一次,这里的线索是,并非总是(尤其是在构建没有考虑 DI 的遗留代码时)是编译时不知道所需服务的类型。因此需要一个“非强”类型的工厂。 IContext 就是这样一个工厂,它可以生成尝试解析的类型的实例。
  • 似乎是 autofac 1.0 的功能,现在 v2 中缺少
【解决方案2】:

首先尽量不要过度使用 IoC 容器。它非常适合“连接”控制器、视图和服务,但需要在运行时创建的对象应该由工厂对象而不是容器创建。否则,您将通过您的代码获得 Container.Resolve 调用,并将其绑定到您的容器。这些额外的依赖破坏了使用 IoC 的目的。在大多数情况下,我只需在应用程序的顶层解决一两个依赖项即可。然后 IoC 容器将递归地解决大多数依赖项。

当我在程序的其他地方需要容器时,这是我经常使用的一个技巧。

public class Container : IContainer
{
    readonly IWindsorContainer container;

    public Container()
    {
        // Initialize container
        container = new WindsorContainer(new XmlInterpreter(new FileResource("castle.xml")));

        // Register yourself
        container.Kernel.AddComponentInstance<IContainer>(this);
    }

    public T Resolve<T>()
    {
        return container.Resolve<T>();
    }
}

我将容器包装在这样的 Container 类中。它将自己添加到构造函数中的包装容器中。现在,需要容器的类可以注入 IContainer。 (该示例适用于温莎城堡,但它可能适用于 AutoFac)

【讨论】:

    【解决方案3】:

    让 IOC 容器在全球范围内可用并不是最佳做法。甚至passing container is not encouraged

    如果不能使用依赖注入(你需要在创建组件后创建\request对象)那么你可以:

    1. 使用手工编码的工厂(工厂注入到组件中,组件使用工厂创建其他对象)
    2. 使用 Autofac delegate factoriesnew auto-generated factories in Autofac 2

    【讨论】:

    • huzzah 不使用容器作为服务定位器
    【解决方案4】:

    Peter Lillevold 上面的回答是正确的 - 您可以通过依赖 IContext 接口从任何组件访问容器。

    如果您真的确实需要实际的容器引用,请参阅 Autofac.Integration.Web.IContainerProviderAccessor。

    【讨论】:

      【解决方案5】:

      执行此操作的常用方法是将容器存储在全局应用程序类的静态变量中。

      【讨论】:

      • 啊,但要小心你存储的容器!你不需要应用程序容器,这是肯定的!
      最近更新 更多