在具有多个入口点的库中应用IoC设计

时间:2015-01-28 19:41:03

标签: c# .net dependency-injection inversion-of-control ioc-container

我正在创建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>();
    }
}

这些解决方案中的任何一个在设计方面都很好吗?还有其他办法可以很好地处理这种情况吗? 或者整个设计可能不是很好?

1 个答案:

答案 0 :(得分:1)

最后,在阅读了Mark Seemann的博客文章后,我决定不在我的NuGet包中使用IoC容器。

相反,我以DI友好的方式设计了我的NuGet包(因此包消费者仍然可以使用IoC方法从其组合根构建所需的对象)。
对于不想关心IoC的软件包消费者,我已经准备好了帮助类,它们只构建了所需的对象(例如&#34; TopicManager&#34;或者#34; QueueManager&#34;来自我的代码示例以默认方式使用通常的&#34; new-new -...&#34;做法。