8

Lets say I have two Controllers: ControllerA and ControllerB. Both of those controllers accept as parameter IFooInterface. Now I have 2 implementation of IFooInterface, FooA and FooB. I want to inject FooA in ControllerA and FooB in ControllerB. This was easily achieved in Ninject, but I'm moving to Simple Injector due to better performance. So how can I do this in Simple Injector? Please note that ControllerA and ControllerB resides in different assemblies and are loaded dynamically.

Thanks

4
  • 2
    This question has come up multiple times on Stackoverflow, and it is my duty to question such design. Although such design is not always wrong, you have to be careful not to violate the Liskov Substitution Principle. So the question is, does ControllerA still works when it is injected with FooB, or does is breaks? If it breaks, you are violating LSP and this means that FooA and FooB should each implement a different interface. Commented Jan 3, 2015 at 9:52
  • @Steven thanks, you gave me something to think of :) Commented Jan 3, 2015 at 16:09
  • @Steven one more thought, the ControllerA will still work when injected with FooB, from this perspective, I can in principle shorten the amount of controllers. The problem is that, the controller feeds IFooInterface with some data from database, which is different for FooA and FooB, so it should be aware of which data to pick from db. Commented Jan 3, 2015 at 16:17
  • It's often hard to discuss application design on Stackoverflow, due to the site's rules. If you're interested, you can start a new discussion on the simpleinjector.codeplex.com forum with some concrete examples of your code (instead of using abstract names like IFoo and Controller1). There are multiple developers on that forum (like me and qujck) who are eager to discuss the design with you and give you some feedback. Commented Jan 4, 2015 at 5:09

2 Answers 2

17

Since version 3 Simple Injector has RegisterConditional method

container.RegisterConditional<IFooInterface, FooA>(c => c.Consumer.ImplementationType == typeof(ControllerA));
container.RegisterConditional<IFooInterface, FooB>(c => c.Consumer.ImplementationType == typeof(ControllerB));
container.RegisterConditional<IFooInterface, DefaultFoo>(c => !c.Handled);
Sign up to request clarification or add additional context in comments.

Comments

5

The SimpleInjector documentation calls this context-based injection. As of version 3, you would use RegisterConditional. As of version 2.8, this feature isn't implemented in SimpleInjector, however the documentation contains a working code sample implementing this feature as extensions to the Container class.

Using those extensions methods you would do something like this:

Type fooAType = Assembly.LoadFrom(@"path\to\fooA.dll").GetType("FooA");
Type fooBType = Assembly.LoadFrom(@"path\to\fooB.dll").GetType("FooB");
container.RegisterWithContext<IFooInterface>(context => {
    if (context.ImplementationType.Name == "ControllerA") 
    {
        return container.GetInstance(fooAType);
    } 
    else if (context.ImplementationType.Name == "ControllerB") 
    {
        return container.GetInstance(fooBType)
    } 
    else 
    {
        return null;
    }
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.