user4336026
user4336026

Reputation:

How to use Ninject & MVC with multiple implementations of a single Interface?

My project is using ASP.NET MVC and Ninject to bind abstract interfaces to concrete implementations so my website Controllers can fetch data. However, now I want to add the option of getting the same set of data from a different location. This will require a different implementation of the abstract interface I use, but all the method calls are the same. I still want to keep using Ninject, but I don't want to just copy the interface I already have and name it something different.

EDIT 1: I just realized I never formally asked a question. How do I tell Ninject and/or the ASP.NET Controller Factories to use one implementation of an abstract class over another based solely on a query string?

Here's an example of what I'm talking about:

// Global.asax.cs

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        // Using Ninject resolver
        NinjectResolver.SetResolver(new NinjectResolver());
    }
}

// NinjectResolver.cs

public class NinjectResolver : IDependencyResolver
{
    private IKernel kernel;

    public NinjectResolver()
    {
        kernel = new StandardKernel();
        AddBindings();
    }

    public void AddBindings()
    {
        // I don't know what to do here:

        //kernel.Bind<IFooModel>().To<FooModelImplementation>();
        //kernel.Bind<IFooModel>().To<FooModelImplementation2>();
    }
}

The interface implementation:

// FooModel.cs

public interface IFooModel
{
    FooData GetData(int dataID);
}

public class FooData
{
    public string Field1 {get; set;}
    public string Field2 {get; set;}
    public string Field3 {get; set;}
    // ...
    public FooData()
    { }
}

public class FooModelImplementation : IFooModel
{
    public FooModelImplementation()
    { }

    public FooData GetData(int dataID)
    {
        // Get data...
    }
}

public class FooModelImplementation2 : IFooModel
{
    public FooModelImplementation2()
    { }

    public FooData GetData(int dataID)
    {
        // Get data from source 2...
    }
}

And my Controller:

// FooController.cs

public FooController : BaseController
{
    private IFooModel mFooModel;

    public FooController(IFooModel fooModel)
    {
        mFooModel = fooModel;
    }

    // http://www.example.com/Foo?dataID=1&location=2
    public ViewResult FooView(int dataID)
    {
        // Here I want the mFooModel to be an instance of FooModelImplementation2
        // because "location" is 2.  How do I do this?
        FooData data = mFooModel.GetData(dataID);
        FooViewModel viewModel = new FooViewModel
        {
            Field1 = data.Field1;
            Field2 = data.Field2;
        };
        return View(viewModel);
    }
}

public class FooViewModel
{
    public string Field1 {get; set;}
    public string Field2 {get; set;}

    public FooViewModel()
    { }
}

Upvotes: 2

Views: 1054

Answers (1)

Remo Gloor
Remo Gloor

Reputation: 32725

Use the factory extension (https://github.com/ninject/Ninject.Extensions.Factory/wiki/Factory-interface%3A-Referencing-Named-Bindings) to inject a factory into the controller instead of the model.

The factory can be used to get named instances. Create two named bindings and choose the appropriate one in the controller.

Upvotes: 1

Related Questions