使用IoC容器; 特别是温莎

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

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

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

我是否创造了一个我传递的单一全球性内容? 当然不是!

我知道我应该这样称呼:

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

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

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

谢谢,

安德鲁

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

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

其他框架不允许您轻松地进入创建过程(如Webforms),因此您必须诉诸此类黑客,或者拉出所需的依赖项(即显式调用容器)。 要获取依赖关系,请使用到此容器的静态网关,如maxnk所描述的那样 。 请注意,通过这样做,您实际上将容器用作服务定位器,它不会分解事物以及控制反转。 (见这里和这里的差异)

希望这能清除你的疑虑。

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

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

我使用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

正如其他答案在这里陈述的那样,有许多选择,我们再次自己去了解我们案例中最好的东西。

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

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

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

我正在使用此接口的实现:

 public interface IResolver { object Resolve(Type type); object Resolve(string name); T Resolve() where T : class; T Resolve(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() where T : class { return Current.Resolve(); } public static T Resolve(string name) where T : class { return Current.Resolve(name); } private static IResolver Current { get { if (_current == null) { _current = new SpringResolver(); } return _current; } } } 

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