快速背景:我已经(大部分)阅读了Mark Seemann的“.NET中的Depdendency Injection”,并准备成为DI忍者。我重构了我的代码库以使用构造函数注入,使用Windsor和SUCCESS连接我的对象!
......除了没有。我的程序最初在它的整个生命周期中显示了几种形式,这最初是通过new()根据需要完成它们来完成的。但是,既然我是NIT(忍者在训练中),我知道新的()是邪恶的,必须放逐到作文根。
问题:我的第一个端到端使用测试涉及向用户显示我的“主”窗口。可以关闭此窗口,以后可以再次启动新版本。这在后DI代码库中运行良好,直到第二次显示表单为止。崩溃。表格已经处理完毕。在连接我的DI容器时,我告诉它使用Form的类来实现一个特定的接口,并且应该期望它给该对象一个单一的生命周期。
问题:所以我很确定解决这个问题的方法是不依赖于表单实现的接口,而是依赖于该接口的工厂。这是我对如何继续的困惑。
我的第一个想法是创建一个与表单具有相同构造函数签名的工厂,存储所有这些依赖项,然后在需要时将new()向上移动一个表单。然而,这感觉就像穷人的DI,我已经经历了使用Windsor容器注册所有东西的麻烦。所以这导致我......
我的第二个想法是创建一个工厂,将DI容器作为依赖项,然后只需.Resolve()每次我需要的东西(这次使用瞬态生活方式)。我怀疑我会挂钩.Closed事件并在那里发布(遵循Register-Resolve-Release模式)。
真正的问题:我喜欢我的第二个想法,但出于某种原因,它感觉像是一个黑客。我不知道是不是因为它(并且有一种更好的方式)或者我的蜘蛛感觉还没有调整到DI。那么,底线,“第二个想法”是一种有效的方法还是代码味道?
另外,如果我将这种方法用于不能提供挂钩到“封闭”事件的方法,那么我应该如何设计释放机制,以便工厂提醒/鼓励我在完成时释放对象? (在某些时候我可能会忘记......)
谢谢!
答案 0 :(得分:1)
最终为我工作的同时仍然保持我的下层不知道DI容器是在较低层创建工厂界面,但然后在我的组合根层实现该工厂。
即:
namespace MyApp.InterfaceLayer
{
public interface IFormFactory
{
IForm GetForm();
}
}
namespace MyApp.CompositionRoot
{
class FormFactory : IFormFactory
{
Castle.Windsor.IWindsorContainer Container { get; set; }
public FormFactory(Castle.Windsor.IWindsorContainer container)
{
Container = container;
}
public IForm GetForm()
{
return Container.Resolve<IForm>();
}
}
}
我当然会注册使用瞬态生活方式实现IForm
的表单,并将我的容器注册为IWindsorContainer
。
到目前为止,这一直像冠军一样!