Webforms和依赖注入

Phi*_*ler 19 c# asp.net dependency-injection webforms castle-windsor

我正在将依赖注入框架引入现有的WebForms应用程序(使用Castle Windsor).

我对DI有很深的经验,并且倾向于非常强烈地支持构造函数注入而不是setter注入.如果您熟悉Webforms,您就会知道ASP.Net框架处理页面和控件对象的构造,从而无法进行真正的构造函数注入.

我目前的解决方案是在Global.asax的Application_Start事件中注册容器,并将容器保存为Global中的公共静态变量.然后,我只需在页面中直接解析我需要的每项服务,或在需要时控制它.所以在每个页面的顶部,我最终得到这样的代码:

private readonly IMyService _exposureManager = Global.IoC.Resolve<IMyService>();
private readonly IMyOtherService _tenCustomersExposureManager = Global.IoC.Resolve<IMyOtherService>();
Run Code Online (Sandbox Code Playgroud)

显然,我不喜欢将所有这些对容器的引用分散在我的应用程序中,或者我的页面/控件依赖关系是非显式的,但我还是找不到更好的方法.

在Webforms中使用DI有更优雅的解决方案吗?

Ste*_*ven 19

我同意@DarinDimitrov认为MVP是一个有趣的选择.但是,在使用遗留应用程序时,将现有页面重写为MVP模式是一项艰巨的工作.在这种情况下,最好从服务定位器模式开始(但在您的UI类中),就像您已经在做的那样.但是,改变一件事.不要将选定的DI容器暴露给应用程序,因为我希望您正在使用该Global.IoC属性.

而是Resolve<T>Global类上创建一个静态方法.这会完全隐藏容器,并允许您交换实现,而无需更改网页中的任何内容.执行此操作时,使用@Wiktor建议的公共服务定位器没有任何优势.公共服务定位器只是不必抽象的东西的另一个抽象(因为你已经使用了抽象容器来抽象Global.Resolve<T>).

遗憾的是,对于Web表单,没有任何好方法可以做到这一点.对于Simple Injector,我编写了一个Web表单集成指南,它基本上描述了该Global.Resolve<T>方法的用法,但也展示了一种测试是否可以创建Page类的方法.该指南也可用于其他DI容器.

顺便说一句,请记住,使用Castle Windsor,您要求的所有内容都必须明确发布(注册解析发布模式).这有点讨厌(IMO)并且不同于其他容器的工作方式,并且当您不能正确执行此操作时可能成为内存泄漏的来源.

最后一点.可以使用Web窗体进行构造函数注入.嗯......有点,因为这会Form在使用默认构造函数创建后使用反射调用重载的构造函数,因此这会导致时间耦合.