0
votes

I'm using Unity and inject all my dependencies. Let's say that I have a Manager class like so

public class Manager : IManager
{
    public Manager(IRepository repository, string customerName) { }
}

And a repository class like:

public class Repository : IRepository
{
    public Repository(string customerName) { }
}

I'm using WCF and will resolve the manager and the repository once per request. I register all my types at service startup, but at startup i do not know the "customerName"-parameter. This will be passed as a parameter to the WCF-service. Which will resolve the manager like this:

public class Service
{
    private IUnityContainer _container;

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

    public void ServiceCall(string customerName)
    {
        var manager = _container.Resolve<IManager<T>>(
            new ParameterOverrides { { "customerName", customerName} });
        manager.DoSomething();
    }
}

This way I can inject the customerName-parameter into the manager on each request. This works fine. But now I also need to inject it to the repository. Is there any way to inject the customerName to the repository-class as well?

I know I can set it manually later, but I would like to have this in the constructor. Also, I don't want the Service to know about the Repository, so I don't want to manually override that parameter.

I could resolve the IRepository with the container in the constructor in the Manager, but i rather just inject it if it's possible.

1
You are already doing it correctly. When you use ParameterOverrides, it will inject the specified value into any parameter named "customerName" in the whole object graph that you are resolving, not just the direct one. Doesn't your current code work? Can you show how you are registering your types? - Yacoub Massad
You are correct. It actually works, I just didn't try it in my actual case since I assumed that it was only injected into the "first layer". - smoksnes
Great! Please note that I was answering your question directly. However, you are using the container as a service locator which is an anti-pattern. Steven's answer below explains more about issues with the way your are doing this. - Yacoub Massad

1 Answers

1
votes

I register all my types at service startup, but at startup i do not know the "customerName"-parameter

In other words, your customerName parameter is runtime data. Injecting runtime data into components during the components' initialization is an anti-pattern.

There are two possible solutions to your problem, but in your your case, the most likely solution is to pass through the parameter through the public API as follows:

public class Service
{
    private readonly IManager _manager;

    public Service(IManager manager) {
        _manager = manager;
    }

    public void ServiceCall(string customerName) {
        _manager.DoSomething(customerName);
    }
}

Here the IManager interface is changed so that the customerName is passed through the DoSomething method. Because the runtime value isn't needed anymore during construction, there is no need to inject the Unity container into the Service (which is a form of the Service Locator anti-pattern).

For the second option, please read this article.