我有一个控制台应用程序,它引用了许多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扩展可以帮助解决这个问题?
答案 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的BarFactory
或BarResolver
,但可以将其重新配置为使用任何内容需要更改客户端代码(CR中的配置有哪些变化)。
http://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html