问题
I have an unusual situation injecting a service into an ASP.NET MVC Controller. The Controller provides a single action to render a side-bar menu on the page, and the service injected into the Controller is a factory to create the side-bar content. The action is decorated with the [ChildActionOnly]
attribute: the side bar can only be rendered when rendering another action.
The difficulty comes in that I want to inject different instances of the side-bar factory abstraction according to the page (= Controller) being requested. Previously, I was doing this using a sort-of abstract factory, which had the inelegant implementation of using the controller name string to determine which concrete factory implementation to use; I've now moved this to a proper abstract factory, and thus need to move the selection of the factory type elsewhere.
My Ninject bindings are currently defined very simply as:
Kernel.Bind<ISideBarFactory>().To<FooSideBarFactory>().InRequestScope();
Kernel.Bind<ISideBarFactory>().To<DefaultSideBarFactory>().InRequestScope();
and as I add more controllers, I will add more instances of the first line. The way I would like to see this working is:
/foo/action
request received- Ninject binds
ISideBarFactory
toFooSideBarFactory
and injects intoSideBarController
- Ninject binds
/bar/action
request received- Ninject binds
ISideBarFactory
toBarSideBarFactory
and injects intoSideBarController
- Ninject binds
/baz/action
request received- No
BazSideBarFactory
exists, so Ninject bindsISideBarFactory
to the default implementation,DefaultSideBarFactory
, and injects intoSideBarController
- No
I've consulted the Ninject wiki page on Contextual Binding, which appears to be what I want in principle, but I haven't found anything documented there which obviously achieves my goal.
回答1:
You can combine reading the route data with Contextual-Binding
Binding
// default binding - used if none of the conditions is met
kernel.Bind<IService>()
.To<DefaultService>()
kernel.Bind<IService>()
.To<BasicService>()
.When(x=> IsRouteValueDefined("controller", "Service"));
kernel.Bind<IService>()
.To<ExtraService>()
.When(x=> IsRouteValueDefined("controller", "ExtraService"));
IsRouteValueDefined()
method
Returns true when route key is defined and specified routeValue
equals route value for route key or is null
.
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().ToUpper() == routeValue.ToUpper();
}
来源:https://stackoverflow.com/questions/14823176/ninject-contextual-binding-on-mvc-request