1

快速背景:我已经(大部分)读完了 Mark Seemann 的“.NET 中的依赖注入”,并准备成为一名 DI 忍者。我重构了我的代码库以使用构造函数注入,使用 Windsor 连接我的对象,并且成功了!

……除了没有。我的程序最初在其整个生命周期中显示了几种形式,这最初是通过根据需要将它们全部 new() 来完成的。但是,既然我是 NIT(忍者培训),我知道 new() 是邪恶的,必须将其放逐到组合根中。

问题:我的第一个端到端使用测试涉及向用户显示我的“主”窗口。可以关闭此窗口,稍后可以再次调出新版本。这在后 DI 代码库中运行良好,直到第二次显示表单。碰撞。表格已经被处理掉了。在连接我的 DI 容器时,我告诉它使用 Form 的类来实现特定的接口,并且正如预期的那样,它为该对象提供了单例生命周期。

问题:所以我很确定解决这个问题的方法是不依赖于表单实现的接口,而是依赖于该接口的工厂。这是我对如何进行感到困惑的地方。

我的第一个想法是创建一个与表单具有相同构造函数签名的工厂,存储所有这些依赖项,然后在需要时创建一个表单。然而,这感觉就像穷人的 DI,我已经经历了在 Windsor 容器中注册所有东西的麻烦。所以这导致我...

我的第二个想法是创建一个工厂,将 DI 容器作为依赖项,然后每次只需要 .Resolve()s (这次使用短暂的生活方式)。我怀疑我会加入 .Closed 事件并在那里释放(遵循 Register-Resolve-Release 模式)。

真正的问题:我喜欢我的第二个想法,但出于某种原因,它感觉就像一个黑客。我不知道这是因为它是(并且有更好的方法)还是我的蜘蛛侠感官还没有针对 DI 进行调整。那么,归根结底,“第二个想法”是一种有效的方法还是一种代码味道?

另外,如果我将这种方法用于不提供挂钩“关闭”事件的方法,那么我应该如何设计释放机制,以便工厂提醒/鼓励我在完成后释放对象?(在某些时候我可能会忘记,否则......)

谢谢!

4

1 回答 1

1

最终为我工作的同时仍然让我的下层不知道 DI 容器是在下层创建一个工厂接口,然后在我的组合根层实现该工厂。

IE:

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.

到目前为止,这一直像冠军一样工作!

于 2013-02-15T22:34:13.050 回答