我正在创建NuGet包,它允许它的使用者轻松地从Azure主题/队列发送/接收消息(加上一些特定于我的需要的额外逻辑)。
包的内部结构非常复杂,有很多依赖项,并且计划由单元测试覆盖,因此决定使用IoC容器(Unity)。
问题是这个包有几个入口点(例如,对象图顶部的一个类用于主题操作,另一个类用于处理队列,等等)。
我读过许多关于IoC的类似文章,到处都说使用它的正确方法是在组合根注册/解析/释放容器(例如,在控制台应用程序中使用Main方法)。但是,如果我们有多个入口点(而且包使用者应该不了解内部包结构),该怎么办?
我在想两种解决方案,它们看起来都不太好.
解决方案#1:
创建消费者将使用的额外公共“助手”类。对于每个“入口点”,每次需要时都配置单独的容器,并使用“寄存器/解析/释放”模式构造所需对象:
public class FooHelper
{
public static ITopicFoo CreateTopicManager()
{
IUnityContainer _container = new UnityContainer()
.RegisterType<ITopicFoo, TopicFoo>()
.RegisterType<ILotOtherDependencies, OtherDependencies>;
var topic = _container.Resolve<ITopicFoo>();
_container.Dispose();
return topic;
}
public static IQueueFoo CreateQueueManager()
{
IUnityContainer _container = new UnityContainer()
.RegisterType<IQueueFoo, QueueFoo>()
.RegisterType<ILotOtherDependencies, OtherDependencies>;
var queue = _container.Resolve<IQueueFoo>();
_container.Dispose();
return queue;
}
}解决方案2:
创建消费者将使用的额外公共“助手”类。使用所有信息配置容器,将其保存在静态属性中,并在需要时使用它来构造对象。
这看起来有点像ServiceLocator反模式,但并不多(除了helper类本身之外,没有人知道这个容器):
public class FooHelper
{
private static readonly IUnityContainer _container;
static FooHelper()
{
IUnityContainer _container = new UnityContainer()
.RegisterType<ITopicFoo, TopicFoo>()
.RegisterType<IQueueFoo, QueueFoo>()
.RegisterType<ILotOtherDependencies, OtherDependencies>;
}
public static ITopicFoo CreateTopicManager()
{
return _container.Resolve<ITopicFoo>();
}
public static IQueueFoo CreateQueueManager()
{
return _container.Resolve<IQueueFoo>();
}
}这些解决方案中的任何一个在设计上都是好的吗?还有其他方法可以很好地处理这种情况吗?
或者这整个设计不是很好?
发布于 2015-03-15 00:38:10
最后,在阅读了Mark的博客文章之后,我决定不再在我的NuGet包中使用NuGet容器。
相反,我已经以一种对DI友好的方式设计了我的NuGet包(所以包使用者仍然可以使用IoC方法从他们的组合根构建所需的对象)。
对于不想关心IoC的包使用者,我已经准备了帮助类,它只是使用通常的“new.”来构造所需的对象(如上面代码示例中的"TopicManager“或"QueueManager”)。接近。
https://stackoverflow.com/questions/28200957
复制相似问题