質問

I have a console app that has references to many dlls. The console app needs to instantiate objects in these dlls. The dlls have dependencies that I'd like to inject into their constructors. My requirement is to do all registrations in the console app - it's the composition root. I can get this far, but how can I persist these registrations into the libraries without passing/referencing the UnityContainer?

I want to avoid a service locator pattern and purely use constructor/method injection. None of this, if possible:

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

Here's what I've got in the console app:

            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);
                    }

When I'm in the class Worker, how would I inject dependencies to other class's constructors? In MVC I can easily handle this in the UnityConfig, but can't figure it out for this scenario. I feel that I should be able to bootstrap everything in the console and be done with it. Are there Unity extensions that can help with this?

役に立ちましたか?

解決

Assuming Worker is registered in the container, either as a concrete type or IWorker:

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

or

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

and then:

worker.Start();

That should be all you need if Worker is at the top of your object graph, and all dependencies flow from it. This is not service location, as you are only calling Resolve() once, and doing so in your composition root. Only the composition root knows about your container.

Edit

From your comments--so assuming this is your setup:

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
{

}

Assuming you had all the registrations set up correctly in Unity, you would just Resolve at the top of the graph:

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

The container would do the rest. "root" is now a container-managed object, and because of this the container can resolve the full graph of dependencies.

This is constructor injection, not service location. The only object in the system that knows anything about the container is the composition root--the only place you call Resolve() is in the Main() method.

Again, I may be misunderstanding something about your question, but what I am describing is pretty much the basic use case of DI + constructor injection.

他のヒント

You set up local factories (aka dependency resolvers) and configure them in the Composition Root. In other words, if you are in Foo class and you need Bar, you use BarFactory or BarResolver that is configured to use Unity but can be reconfigured to use anything without the need to change client code (what changes is the configuration in the CR).

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top