Ninject injection based on a route data value

2019-01-18 07:55发布

问题:

We've got an ASP.NET MVC application, that has a number of different areas. There are 2 areas that use the same C# classes from our service layer, but target different underlying data. I want these services to get different dependencies based on a value in the route data.

It's hard to explain, and I'm paraphrasing my class/area names. To illustrate:

When the 'Code' is in the route data, I want to get different dependencies injected to when it is not present.

I understand there is the .When() method you can use to do conditional bindings, but I'm not sure how to get the route data from there. I could possibly also do it based on the area that it was called from, however thats not preferable in my instance (I think we may use the Code in that other area)

Is this possible?

回答1:

This works for me (it is for standard route configuration "{controller}/{action}/{id}")

Ninject configuration

protected override Ninject.IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<IService>()
        .To<ServiceA>()
        .When(x => IsRouteValueDefined("id", null));
    kernel.Bind<IService>()
        .To<ServiceB>()
        .When(x => !IsRouteValueDefined("id",null));
    return kernel;
}
// just sample condition implementation
public static bool IsRouteValueDefined(string routeKey, string routeValue)
{
    var mvcHanlder = (MvcHandler)HttpContext.Current.Handler;
    var routeValues = mvcHanlder.RequestContext.RouteData.Values;
    var containsRouteKey = routeValues.ContainsKey(routeKey);
    if (routeValue == null)
        return containsRouteKey;
    return containsRouteKey && routeValues[routeKey].ToString() == routeValue;
}

it will use

  • ServiceA for routes: /home/index/1, /home/index/2 etc.
  • ServiceB for routes: / , /home/index etc.