28

我认为这个问题的答案是如此明显,以至于没有人费心写这个,但已经晚了,我真的无法理解这个问题。

我一直在阅读 IoC 容器(在本例中为温莎),但我想念您如何从代码的各个部分与容器对话。

我得到了 DI,我一直在做可怜的人 DI(空构造函数调用具有默认参数实现的重载注入构造函数)一段时间,我完全可以看到容器的好处。但是,我错过了一条重要信息;每次需要从容器中获取服务时,您应该如何引用容器?

我是否创建了一个传递的全局实例?肯定不是!

我知道我应该这样称呼:

WindsorContainer container = new WindsorContainer(new XmlInterpreter());

(例如)当我想加载我的 XML 配置时,我该如何处理容器?之后每次创建一个新容器是否通过一些内部静态majicks或其他方式持久化加载的配置,或者我是否每次都必须重新加载配置(我猜不是,或者生命周期无法工作)。

未能理解这一点使我无法弄清楚生命周期是如何工作的,并继续使用一些 IoC 可怕的东西

谢谢,

安德鲁

4

5 回答 5

24

99% 的情况是每个应用程序一个容器实例。通常你在 Application_Start 中初始化它(对于一个网络应用程序),像这样

在那之后,这真的取决于容器的消费者。例如,一些框架,如MonorailASP.NET MVC允许您拦截实例(在本例中为控制器)的创建,因此您只需在容器中注册控制器及其依赖项即可,只要您获得request 容器负责注入每个控制器及其依赖项。参见例如这个 ASP.NET MVC 控制器。在这些框架中,您几乎不需要在类中调用甚至引用容器,这是推荐的用法。

其他框架不允许您轻松进入创建过程(例如 Webforms),因此您必须求助于像这样的 hack ,或者提取所需的依赖项(即显式调用容器)。要拉取依赖项,请使用一个静态网关到容器,例如这个或maxnk描述的那个。请注意,通过这样做,您实际上将容器用作服务定位器,它不会解耦事物以及控制反转。(见这里这里的区别)

希望这能消除您的疑虑。

于 2008-12-15T03:10:40.490 回答
3

通常,您希望在整个应用程序的生命周期内只保留一个实例。我大部分时间做的是在应用程序启动时初始化容器,然后我使用类型化工厂进行容器不感知的对象拉取。

其他流行的方法是用静态类包装容器实例并使用该静态类来访问您的(单例)容器。您可以在此处的 Ayende 的 Rhino.Commons 库中找到一个示例。然而,这种方法有严重的缺点,应该避免。

于 2008-12-22T22:15:15.337 回答
1

我使用 Michael Puleio 的博客中关于使用 HttpModule 处理使用 Unity 构建我的依赖项的示例。http://blogs.msdn.com/mpuleio/archive/2008/07/17/proof-of-concept-a-simple-di-solution-for-asp-net-webforms.aspx

于 2008-12-15T14:19:55.663 回答
1

正如这里的其他答案所说,有很多选择,我们再次留给自己找出在我们的情况下最好的选择。

也就是说,IMO 拥有一个可以在整个应用程序中访问的全局容器,这在某种程度上打破了隔离,因为现在很多代码都依赖于一个全局类。此外,对于拆分为多个程序集的应用程序,必须使所有这些程序集都可以访问全局容器。

使用Unity,您实际上可以在构造函数中使用 IUnityContainer 参数,当您解析类时,容器会自动将自身注入到实例中。这样,对于需要解析其他服务的服务,您可以在容器中传递,而不是强制类引用外部类。

不确定其他框架如何支持这种情况(Windsor 将注入IKernel)。

于 2009-03-23T14:18:09.453 回答
0

我正在使用这个接口的实现:

public interface IResolver
{
    object Resolve(Type type);
    object Resolve(string name);

    T Resolve<T>() where T : class;
    T Resolve<T>(string name) where T : class;
}

它实际上包装在全局静态类中,例如:

public static class Resolver // : IResolver
{
    private static IResolver _current;

    public static object Resolve(Type type)
    {
        return Current.Resolve(type);
    }

    public static object Resolve(string name)
    {
        return Current.Resolve(name);
    }

    public static T Resolve<T>() where T : class
    {
        return Current.Resolve<T>();
    }

    public static T Resolve<T>(string name) where T : class
    {
        return Current.Resolve<T>(name);
    }

    private static IResolver Current
    {
        get
        {
            if (_current == null)
            {
                _current = new SpringResolver();
            }

            return _current;
        }
    }
}

此外,我正在尝试遵循简单的规则 - 尽可能少地使用 Resolver 类,而是在需要这些服务的对象中注入服务。

于 2008-12-15T00:05:56.947 回答