3

我有一个不寻常的情况,将服务注入 ASP.NET MVC 控制器。Controller 提供了一个单一的动作来渲染页面上的侧边栏菜单,并且注入到 Controller 中的服务是创建侧边栏内容的工厂。动作用[ChildActionOnly]属性修饰:侧边栏只能在渲染另一个动作时被渲染。

困难在于我想根据请求的页面(=控制器)注入侧栏工厂抽象的不同实例。以前,我使用一种抽象工厂来执行此操作,它使用控制器名称字符串来确定要使用哪个具体工厂实现的不优雅的实现;我现在已将其移至适当的抽象工厂,因此需要将工厂类型的选择移至其他地方。

我的 Ninject 绑定目前非常简单地定义为:

Kernel.Bind<ISideBarFactory>().To<FooSideBarFactory>().InRequestScope();
Kernel.Bind<ISideBarFactory>().To<DefaultSideBarFactory>().InRequestScope();

随着我添加更多控制器,我将添加更多第一行的实例。我希望看到这个工作的方式是:

  • /foo/action收到请求
    • Ninject 绑定ISideBarFactoryFooSideBarFactory注入SideBarController
  • /bar/action收到请求
    • Ninject 绑定ISideBarFactoryBarSideBarFactory注入SideBarController
  • /baz/action收到请求
    • BazSideBarFactory存在,所以 Ninject 绑定ISideBarFactory到默认实现DefaultSideBarFactory,并注入到SideBarController

我在Contextual Binding上查阅了 Ninject wiki 页面,这似乎是我原则上想要的,但我还没有发现任何明显可以实现我的目标的文档。

4

1 回答 1

3

您可以将读取路线数据与Contextual-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()方法

当定义并指定routeValue路由键等于路由键的路由值或 is时返回 true 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();
}
于 2013-02-12T08:03:30.360 回答