Search code examples
c#asp.netasp.net-mvcdependency-injectionunity-container

MVC 5 / UnityConfig - Same Interface - Multiple Implementations


So I have this basic Interface:

public interface ISearchable
{
    List<AutocompleteResult> Search(string term);
}

And two classes which implement this interface:

First Class:

public class LandlordReader :ISearchable
{
    public List<AutocompleteResult> Search(string term)
    {
        ....
    }
}

Second Class:

public class CityReader : ISearchable
{
    public List<AutocompleteResult> Search(string term)
    {
       ....
    }
}

From this point on, I'm in the dark... In UnityConfig.cs I tried to register them by giving them a name:

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<ISearchable, CityReader>("City");
    container.RegisterType<ISearchable, LandlordReader>("Landlord");
}

In the MVC Controller I have no idea on what to specify (IN THE CONSTRUCTOR) - to tell it that I want one or another:

public LandlordController(ISearchable searcher)
{
    // I want the LandlordReader here, but in the CityController, I want the CityReader....
    this.searcher = searcher;
}

I'm quite a noob, regarding DI and UnityInjector, so a full working example would be good. I got lots of advices up to this point (use generic interface, use unity factory) - but trying them myself, none worked.

I know in ASP.NET Core there's an attribute you can directly specify in the constructor's parameter list, but I am currently working in MVC5.

Thanks. Finished a long post. Phew.


Solution

  • You can try one of these options if suitable in your scenario.

    1

    Using Named Serivce Injection

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<ISearchable, CityReader>("City");
        container.RegisterType<ISearchable, LandlordReader>("Landlord");
    }
    
    public LandlordController([Dependency("Landlord")]ISearchable searcher)
    {
        this.searcher = searcher;
    }
    

    2

    public interface ISearchable<T> where T : class
    {
    //..............
    }
    
    public class LandlordReader : ISearchable<LandlordReader>
    {
        public List<AutocompleteResult> Search(string term)
        {
            ....
        }
    }
    
    public class CityReader : ISearchable<CityReader>
    {
        public List<AutocompleteResult> Search(string term)
        {
           ....
        }
    }
    public static void RegisterTypes(IUnityContainer container)
    {
            container.RegisterType<ISearchable, CityReader>("City");
            container.RegisterType<ISearchable, LandlordReader>("Landlord");
    }
    

    and then when using in the constructor do this

        private readonly ISearchable<CityReader> _cityReadersearcher;
        private readonly ISearchable<LandlordReader> _landLordsearcher;
        public LandlordController(ISearchable<CityReader> cityReadersearcher, 
         ISearchable<LandlordReader> landLordsearcher)
        {
             _cityReadersearcher= _cityReadersearcher;
            _landLordsearcher = landLordsearcher;
        }