Simple Injector with dependency on two objects tha

2019-07-01 22:57发布

问题:

I'm writing an application (exposed via an ASP.NET web API) that's entire purpose is to consume two data sources, and expose the similarities and differences. So the API has the following setup:

public class FooController : WebAPI
{
    public FooController(IFooRepository repoFromSourceA, IFooRepository repoFromSourceB)
    {
        ...
    }
}

Maintaining the distinction of which one is of which source (SourceA and SourceB cannot be interchanged) seems to make container.RegisterCollection(..) impossible (or very dangerous) to use. Further, since one class is consuming both implementations, Decorator seems to not be fitting.

How, then, would I setup this dependency injection?

回答1:

The question you have is a very common one. Many developers struggle with this, when starting with Dependency Injection. When dealing with this, it is always important to find out whether you are violating the Liskov Substitution Principle (LSP), because when you do, you should instead use two separate interfaces. Never forget: an interface is more than just the method signatures. It is a contract of how implementations of that contract behave and what they return.

Your comment seems to indicate that you are not violating the LSP, since their behavior is identical and they can be swapped for one another (it might break the application, but it will not break the consumer).

The way to handle this in Simple Injector is by using context based injection using the RegisterConditional methods. For instance:

container.RegisterConditional<IFooRepository, FooRepoA>(
    c => c.Consumer.Target.Parameter.Name.Contains("SourceA"));
container.RegisterConditional<IFooRepository, FooRepoB>(
    c => c.Consumer.Target.Parameter.Name.Contains("SourceB"));

Here the RegisterConditional method is supplied with a predicate that constructor parameter of the consumer where the dependency is injected into, has a name that contains either "SourceA" or "SourceB".