我正在创建NuGet包,允许其消费者轻松地从Azure主题/队列发送/接收消息(以及一些特定于我需要的额外逻辑)。
包内部结构非常复杂,具有很多依赖性,计划用单元测试来覆盖,因此决定使用IoC容器(Unity)。
问题是这个包有几个入口点(例如,对象图顶部的一个类用于操作主题,另一个类用于操作队列等)。
我阅读了很多关于IoC的类似文章,并且在任何地方都说它使用它的正确方法是在组合根处注册/解析/释放容器(例如在Console应用程序的情况下在Main方法中)。 但是,如果我们有多个入口点该怎么办(并且包消费者应该对内部包结构一无所知)?
我在考虑两种解决方案,而且它们都看起来不太好......
解决方案#1:
创建额外的公共"帮助"消费者将使用的类。对于每个"入口点"使用" register / resolve / release"配置单独的容器并构造所需的对象;每当他们需要时模式:
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:
创建额外的公共&#34;帮助&#34;消费者将使用的类。使用所有信息配置容器,将其保存在静态属性中,并在需要时使用它来构造对象
这看起来像ServiceLocator反模式,但并不多(除了帮助器类本身之外没有人知道这个容器):
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>();
}
}
这些解决方案中的任何一个在设计方面都很好吗?还有其他办法可以很好地处理这种情况吗? 或者整个设计可能不是很好?
答案 0 :(得分:1)
最后,在阅读了Mark Seemann的博客文章后,我决定不在我的NuGet包中使用IoC容器。
相反,我以DI友好的方式设计了我的NuGet包(因此包消费者仍然可以使用IoC方法从其组合根构建所需的对象)。
对于不想关心IoC的软件包消费者,我已经准备好了帮助类,它们只构建了所需的对象(例如&#34; TopicManager&#34;或者#34; QueueManager&#34;来自我的代码示例以默认方式使用通常的&#34; new-new -...&#34;做法。