我有一个小应用程序(Win Forms),我有两个不同的存储库(SQL Server和Redis)都实现了一个接口IFilterRepo。 我还有一个依赖于IFilterRepo的服务类。客户端(Win Form)调用服务来访问过滤器数据。
我希望客户端有两个单选按钮,用户可以在其中选择要使用的repo。这就是我的困境。我应该如何告诉服务哪个具体类实例化为IFilterRepo?我的意思是,所有Unity注册和对它的引用都应该在组合根目录中完成。在这种情况下,这种“规则”真的可能吗?
答案 0 :(得分:1)
这是一个常见问题,答案通常是使用抽象工厂。
这是一篇关于这个主题的好文章(我一直链接这个,但我没写过):
http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
如文章中所述,您可以使工厂成为组合根的一部分,以便在工厂内调用container.Resolve()不会违反该规则。
修改强>
您将使用名称(字符串)注册服务的不同实现:
http://msdn.microsoft.com/en-us/library/ff648211.aspx
myContainer.RegisterType<IMyService, CustomerService>("Customers");
然后你的工厂会以这个名字解决:
public IFilterRepo Create(string myName)
{
return myContainer.Resolve<IFilterRepo>(myName);
}
修改2
您在上次评论中提出的问题在这里有点回答,但简而言之:您的工厂本身会实现一个界面,并将通过容器解析和注册。
作为一般事项,我不建议直接从后面的代码访问存储库 - 我至少会考虑使用分层架构(或者更好的Onion架构,它与DI一起工作得非常好)。
最后,我多年没有完成WinForms的开发,但我不认为它与使用容器/ Composition Root完全吻合,因为你无法完全控制对象的生命周期(你不能将服务注入到表单构造函数中)。 ASP.Net Webforms也是如此。因此,您可能必须为工厂使用属性注入和表单中所需的其他服务,或者直接通过调用容器的静态实例(container.Resolve())来解析工厂。这是不完美的,违背了具有组合根的想法,而不是服务位置。
您可以使用google关键字“Unity WinForms”和/或“[OtherDIFramework] Winforms”来获取有关如何构建代码的一些想法。