winforms – 将Castle.Windsor与Windows窗体应用程序一起使用
到目前为止,我一直在使用ASP.NET MVC学习使用Castle.Windsor的IoC / DI,但我有一个在Windows Forms中完成的辅助项目,我想知道是否有一种有效的方法来使用它那.
我的问题在于表单,服务等的创建.在ASP.NET MVC中,有一种“激活器”可以做到这一点,但在Windows窗体中并非如此.我必须创建一个像var form = new fclsMain();的新表单,所以一个像… class fclsMain : System.Windows.Forms.Form { private readonly ISomeRepository<SomeClass> someRepository; fclsMain(ISomeRepository<SomeClass> someRepository) { this.someRepository = someRepository; } } 瀑布有点短.我基本上要做… var form = new fclsMain(IoC.Resolve< ISomeRepository< SomeClass>); 正如我在至少三个问题中所指出的那样,并不聪明,因为据说这不是IoC的“正确”用法. 那么我如何使用Castle.Windsor和Windows Forms?有没有办法设计Form Activator或其他东西?我真的输了,如果我不能制作一个我可以解决的静态IoC容器,我该怎么办?
要在整个应用程序中使用相同的Castle容器,请创建一个静态类,如:
public static class CastleContainer { private static IWindsorContainer container; public static IWindsorContainer Instance { get { if (container == null) { container = new WindsorContainer(); } return container; } // exposing a setter alleviates some common component testing problems set { container = value; } } // shortcut to make your life easier :) public static T Resolve<T>() { return Instance.Resolve<T>(); } public static void Dispose() { if (container != null) container.Dispose(); container = null; } } 然后在Main()方法中注册/安装所有组件.您还可以挂钩到应用程序关闭事件以调用Dispose()(尽管这并不重要). Castle实际上在quick-start guide中使用了Windows Forms应用程序. 编辑: 我上面展示的模式是服务定位器的变体,有些人称之为反模式.它的声誉很差,因为除了其他原因之外,它还引用了Windsor的代码库.理想情况下,您应该只调用一次container.Resolve< ...>()来创建根表单.所有其他服务&形式通过构造函数注入. 实际上,您可能需要再调用一些Resolve,特别是如果您不想在启动时加载应用程序的每个角落.在Web世界中,最佳实践是将容器交给Web框架.在Windows窗体世界中,您需要实现自己的服务定位器,如上所述. (是的,将容器交给ASP.NET MVC框架仍然是服务定位器模式). 我编辑了上面的代码示例,以便静态容器是可注入的;没有资源在静态上下文中被束缚.如果您最终创建自己的服务定位器,您可能还需要创建一个像这样的测试实用程序,以使测试更容易. public static class TestUtilities { public static IContainer CreateContainer(Action<IContainer> extraConfig = null) { var container = new WindsorContainer(); // 1. Setup common mocks to override prod configuration // 2. Setup specific mocks,when provided if (extraConfig != null) extraConfig(container); // 3. Configure container with production installers CastleContainer.Instance = container; return container; } } 这使得创建一个看起来很像生产版本的新容器的快捷方式,但一些服务被模拟取代.一些示例测试可能如下所示: [Test] public void SubComponentWorksGreat() { using (var container = TestUtilities.CreateContainer()) { var subComponent = container.Resolve<SubComponent>(); // test it... } } [Test] public void SubComponentWorksGreatWithMocks() { var repoMock = new Mock<IRepository>(); using (var container = TestUtilities.CreateContainer(c => c.Register(Component.For<IRepository>().Instance(repoMock.Object)))) { var subComponent = container.Resolve<SubComponent>(); // test it with all IRepository instances mocked... } } 最后一点.为每个测试创建一个完整的容器可能会变得昂贵.另一种选择是创建完整容器,但仅使用嵌套容器进行实际测试. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |