我刚刚开始使用Unity,而且我无法找到有关在何处声明UnityContainer对象的建议。我见过的大多数示例只包含一个方法,其中UnityContainer对象在顶部声明,然后定义其映射,然后解析一些对象类型。但是,当您需要在整个程序中的多个位置访问容器时,如何处理容器?例如,用户点击一个按钮打开一个新窗口,该窗口需要一个控制器,它本身需要解决多个服务?我还希望Unity能够成为单身人士的一些服务,所以这不意味着我必须在整个程序中只有一个UnityContainer实例来管理这些单身人士吗?
我的第一个想法是让我的主程序类具有静态UnityContainer属性或者暴露某种管理单个UnityContainer实例的UnityContainerFactory类,但这两种方法看起来都很糟糕,因为它们创建了很多东西的全局属性依赖于。
这种做法的可接受方式是什么?
答案 0 :(得分:2)
使用Seemann的话:
尽可能接近应用程序的入口点。
看看伟大的Seemann的http://blog.ploeh.dk/2011/07/28/CompositionRoot/。
我认为主容器是一个与您的应用程序一起处理的静态字段是完全可以接受的,只需记住不要将您的类绑定到容器中。
注意到所谓的"服务定位器" (再次来自Seemann:http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/)
在哪里声明它实际上取决于应用程序,我会选择owin应用程序的启动类或控制台/ WPF应用程序的Main方法。
答案 1 :(得分:2)
如另一个答案中所述,您应该在Composition Root中撰写整个对象图。
不要将容器声明为静态字段,因为这会鼓励开发人员将其用作is an anti-pattern的服务定位器。
如何解决您的问题?
以下是您的特殊WinForms案例的示例:
在Program.Main方法中,创建容器,注册服务(需要在其他窗口中使用的依赖项),然后解析主窗体并按以下方式运行:
UnityContainer container = new UnityContainer();
container.RegisterType<IService, Service>();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(container.Resolve<MainForm>());
在MainForm中,声明对Func<SecondForm>
的依赖关系,其中SecondForm
是单击按钮时需要从主窗体创建的窗体。请考虑主表单文件中的以下代码:
public partial class MainForm : Form
{
private readonly Func<SecondForm> m_SecondFormFactory;
public MainForm(Func<SecondForm> second_form_factory)
{
m_SecondFormFactory = second_form_factory;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SecondForm second_form = m_SecondFormFactory();
second_form.Show();
}
}
请注意Func<SecondForm>
充当某种工厂。我在这种情况下使用它,因为unity有一个feature来支持通过Func
延迟构建依赖项。
SecondForm
依赖于此IService
:
public partial class SecondForm : Form
{
private readonly IService m_Service;
public SecondForm(IService service)
{
m_Service = sevice;
InitializeComponent();
}
//Use service here
}
您现在可以使用第二种形式的IService
。