IoC容器的用法;特别是温莎

时间:2008-12-14 23:52:09

标签: c# inversion-of-control castle-windsor

我认为这个问题的答案非常明显,以至于没有人为此写过不好的文章,但是它已经很晚了,我真的无法理解这个问题。

我一直在阅读IoC容器(在这种情况下是Windsor),我很想念你如何从代码的各个部分与容器对话。

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

我是否创建了一个我传递的全局内容?当然不是!

我知道我应该这样称呼:

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

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

不理解这会阻止我弄清楚生命周期是如何工作的,并且继续使用一些IoC的功能

谢谢,

安德鲁

5 个答案:

答案 0 :(得分:24)

99%的案例是每个应用程序的一个容器实例。通常,您在Application_Start(对于Web应用程序)中初始化它,like this

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

其他框架不允许您轻松地进入创建过程(如Webforms),因此您必须求助于this one之类的黑客攻击,或所需的依赖项(即,显式调用容器)。要提取依赖关系,请使用容器的静态网关,如this onemaxnk描述的容器。请注意,通过这样做,您实际上使用容器作为服务定位器,它不会分解事物以及控制反转。 (参见差异herehere

希望这能解决你的疑虑。

答案 1 :(得分:3)

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

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

答案 2 :(得分: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

答案 3 :(得分:1)

正如其他答案在这里说的那样,有很多选择,我们还是要自己去弄清楚在我们的情况下什么是最好的。

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

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

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

答案 4 :(得分: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类,而是在需要这些服务的对象中注入服务。