2

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()
    { }
}

1 Answers1

1

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.

Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • Hi @Remo. Please do you think you could take at look a this question? http://stackoverflow.com/questions/40198294/how-to-configure-ninject-so-that-it-creates-a-single-instance-per-controller?noredirect=1#comment67673663_40198294 – eddy Oct 23 '16 at 18:24