0

How tell to Unity.WebApi dependency injection framework, inject the correct class in the correct controller?

DI Project Container

public class UnityContainerConfig
{

    private static IUnityContainer _unityContainer = null;

    public static IUnityContainer Initialize()
    {
        if (_unityContainer == null)
        {
            _unityContainer = new Microsoft.Practices.Unity.UnityContainer()  
            .RegisterType<IMyInterface, MyClass1>("MyClass1")
            .RegisterType<IMyInterface, MyClass2>("MyClass2")
     }
}

-MVC PROJECT-

public static class UnityConfig
{
    public static void RegisterComponents()
    {            
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(DependencyInjection.UnityContainer.UnityContainerConfig.Initialize());
    }
}

Controller 1:

 private IMyInterface _myInterface
 ///MyClass1
 public XController(
         IMyInterface myInterface
        )
    {
        _myInterface = myInterface
    }

Controller 2:

 private IMyInterface _myInterface
 ///MyClass2
 public YController(
         IMyInterface myInterface
        )
    {
        _myInterface = myInterface
    }
Mario Guadagnin
  • 476
  • 7
  • 17
  • 3
    Your question is about strategy and/or facade, but it is not clear based on your question how either of them would be useful. Are you trying to make conditional resolving of the `IMyInterface` type by controller? – NightOwl888 Jan 20 '17 at 19:52
  • 1
    In other words, why criteria would be used to pick which `IMyInterface` implementation for each controller? i.e., Unity can't guess at it. – Peter Ritchie Jan 20 '17 at 20:33
  • @NightOwl888 yes, i'm trying to do it. "if(XController) for IMyInterface MyClass1 if(YController) for IMyInterface MyClass2". I search on stackoverflow but I didn't find any answer so far. – Mario Guadagnin Jan 23 '17 at 10:48
  • 1
    To use the strategy pattern, see [Dependency Injection Unity - Conditional resolving](http://stackoverflow.com/questions/32296209/dependency-injection-unity-conditional-resolving). That said, this looks more like a design issue - being that both `IMyInterface` instances are not being used in the same controller, you should instead make specialized interfaces (`public interface IXControllerMyInterface : IMyInterface {}` and `public interface IYControllerMyInterface : IMyInterface {}`) and register each type with your container, since there is no actual runtime swap here. – NightOwl888 Jan 23 '17 at 11:15
  • @NightOwl888 That solution is great! but, there is only one problem. I tried to solve some problems like it using "InjectionConstructor", once I used it, I had to specify the others constructors too. Example: if MyClass1 has 2 others interfaces on the constructor, i also had to specify and use the "InjectionConstructor" on unity container for these others interfaces, otherwise, it throws and exception error on the application start up. (Could you understand me? it's really hard to explain without showing any code and english is not first language.) – Mario Guadagnin Jan 23 '17 at 13:10
  • 1
    I think I understand what you mean. I haven't found a way to work around that with Unity, which is one reason I don't use it. Other containers (such as StructureMap or Autofac) allow you to specify just one parameter and the others remain their defaults. But then, my recommendation was not to use the strategy pattern for this scenario because it doesn't make sense to use it here. You should instead design your interfaces to be unique (one way to do this is `IMyInterface` so you have an interface type that matches the controller type). – NightOwl888 Jan 23 '17 at 15:38
  • @NightOwl888 the ideia of the interface `IMyInterface` seems the easiest way to solve the problem for this scenario. You can set it as the answer. Thanks ;) – Mario Guadagnin Jan 23 '17 at 16:34

1 Answers1

2

Rather than using a strategy or facade to solve this, a better solution would be to redesign your interfaces to be unique per controller. Once you have a unique interface type, your DI container will automatically inject the right service into each controller.

Option 1

Use a generic interface.

public interface IMyInterface<T>
{
}

public class XController
{
    private readonly IMyInterface<XClass> myInterface;

    public XController(IMyInterface<XClass> myInterface)
    {
        this.myInterface = myInterface;
    }
}

public class YController
{
    private readonly IMyInterface<YClass> myInterface;

    public YController(IMyInterface<YClass> myInterface)
    {
        this.myInterface = myInterface;
    }
}

Option 2

Use interface inheritance.

public interface IMyInterface
{
}

public interface IXMyInterface : IMyInterface
{
}

public interface IYMyInterface : IMyInterface
{
}

public class XController
{
    private readonly IXMyInterface myInterface;

    public XController(IXMyInterface myInterface)
    {
        this.myInterface = myInterface;
    }
}

public class YController
{
    private readonly IYMyInterface myInterface;

    public YController(IYMyInterface myInterface)
    {
        this.myInterface = myInterface;
    }
}
NightOwl888
  • 55,572
  • 24
  • 139
  • 212