2
votes

What I want: Resolve object A, and inside object A, I want use same container to resolve object C:

public static void Work()
{
    IUnityContainer con = new UnityContainer();
    con.RegisterType<IA, A>();
    con.RegisterType<IB, B>();
    con.RegisterType<IC, C>();

    var a = con.Resolve<IA>();
}


interface IA { }
interface IB { }
interface IC { }

class A : IA
{
    public A(IB b, IUnityContainer con)
    {
        for (int i = 0; i < 10; i++)
        {
            var c = con.Resolve<IC>();
        }
    }
}

class B : IB { };
class C : IC { };

Problem: On many sites I see that injecting container is bad idea, but how to be in such situation?

EDIT 1

Service Locator is an anti-pattern. So if it is okay to use Service Locator with IoC Container, why is it okay?

2
What I'm missing from your question is what problem you are trying to solve here. Why are you need to resolve IC multiple times and why do you need to do this inside A's constructor. Can you make your use case more concrete by using real names and describe what you are doing and why? - Steven
@Steven I'm want to use container in many places in my application. My solution was to inject that container everywhere. I know that injecting it everywhere is bad idea, but Service Locator is known as anti-pattern and static class even worse. - Stas BZ
That's the part that was clear to me. What's unclear to me is your specific use case. Please elaborate with a real example, not with classes like A and IC. - Steven

2 Answers

3
votes

You should not pass a direct reference to your class, cause this will make your code dependant on the used IOC container (here UnityContainer) and makes it a little harder for unittests.

If your class A needs multiple instances of C you should define a factory for this case and pass an instance of that factory to your class A. Your real factory can reference the UnityContainer. For unittests you can mock the interface and pass a mocked instance to your class A.

Code for this would look something like this.

public interface IClassICFactory
{
    IC CreateInstance();
}

public class ClassICUnityContainerFactory : IClassCFactory
{
    private IUnityContainer _container;

    public ClassICUnityContainerFactory(IUnityContainer container)
    {
        _container = container;
    }

    public IC CreateInstance()
    {
        return _container.Resolve<C>();
    }
}

class A : IA
{
    public A(IB b, IClassICFactory factory)
    {
        for (int i = 0; i < 10; i++)
        {
            var c = factory.CreateInstance();
        }
    }
}
0
votes

While technically it works, it's a bit 'containerception' and would lead to huge amounts of confusion. I create static factory classes for containers that deal with this kind of thing. You class instances resolved by the container should just be concerned with what ever they are meant to do, and not further resolving of other instances.