在控制台应用程序中使用Unity 3.5构造函数注入 - C#

时间:2014-05-05 18:44:47

标签: c# inversion-of-control unity-container ioc-container

我有一个控制台应用程序,它引用了许多dll。控制台应用程序需要实例化这些dll中的对象。这些dll具有我想要注入其构造函数的依赖项。我的要求是在控制台应用程序中进行所有注册 - 它是组合根。我可以做到这一点,但是如何在不传递/引用UnityContainer的情况下将这些注册持久存储到库中?

我想避免服务定位器模式,纯粹使用构造函数/方法注入。如果可能的话,这些都不是:

_container.Resolve<IData>()  // not what I want

以下是我在控制台应用中的内容:

            static IUnityContainer _container;

            static void Main(string[] args)
                    {
                        LoadContainer();
                        var worker = new Worker(_container.Resolve<IData>()); // I don't like this
                        worker.Start();
                    }

            private static void LoadContainer()
                    {
                        _container = new UnityContainer();

                        // This will register all types with a ISample/Sample naming convention 
                        _container.RegisterTypes(
                            AllClasses.FromLoadedAssemblies(),
                            WithMappings.FromMatchingInterface,
                            WithName.Default);
                    }

当我在班级Worker时,我如何将依赖项注入其他类的构造函数?在MVC中,我可以在UnityConfig中轻松处理此问题,但无法弄清楚这种情况。我觉得我应该能够在控制台中引导所有内容并完成它。是否有Unity扩展可以帮助解决这个问题?

2 个答案:

答案 0 :(得分:3)

假设Worker已在容器中注册,可以是具体类型,也可以是IWorker

var worker = _container.Resolve<IWorker>();

var worker = _container.Resolve<Worker>();

然后:

worker.Start();

如果Worker位于对象图的顶部,并且所有依赖关系都从它流出,那么这应该是您所需要的。这不是服务位置,因为您只调用Resolve()一次,并在组合根目录中执行此操作。只有组合根知道你的容器。

修改

根据您的评论 - 假设这是您的设置:

public class Root
{
    private readonly A _a;

    public Root(A a)
    {
        if (a == null) throw new ArgumentNullException("a");
        _a = a;
    }
}

public class A
{
    private readonly B _b;

    public A(B b)
    {
        if (b == null) throw new ArgumentNullException("b");
        _b = b;
    }
}

public class B
{
    private readonly C _c;

    public B(C c)
    {
        if (c == null) throw new ArgumentNullException("c");
        _c = c;
    }
}

public class C
{

}

假设您已在Unity中正确设置了所有注册,您只需在图表的顶部解析:

var root = _container.Resolve<Root>();

容器会完成其余的工作。 &#34;根&#34;现在是一个容器管理的对象,因此容器可以解析依赖关系的完整图形。

这是构造函数注入,不是服务位置。系统中唯一知道容器的对象是组合根 - 你调用Resolve()的唯一地方是Main()方法。

同样,我可能会误解你的问题,但我所描述的几乎是DI +构造函数注入的基本用例。

答案 1 :(得分:1)

您设置本地工厂(也称为依赖项解析器)并在Composition Root中配置它们。换句话说,如果您在Foo课程中并且需要Bar,则可以使用配置为使用Unity的BarFactoryBarResolver,但可以将其重新配置为使用任何内容需要更改客户端代码(CR中的配置有哪些变化)。

http://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html