【问题标题】:Ninject Contextual Binding on MVC RequestNinject MVC 请求的上下文绑定
【发布时间】:2013-02-11 23:54:46
【问题描述】:

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

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

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

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

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

  • /foo/action 收到请求
    • Ninject 将ISideBarFactory 绑定到FooSideBarFactory 并注入到SideBarController
  • /bar/action 收到请求
    • Ninject 将ISideBarFactory 绑定到BarSideBarFactory 并注入到SideBarController
  • /baz/action 收到请求
    • 不存在BazSideBarFactory,因此Ninject将ISideBarFactory绑定到默认实现DefaultSideBarFactory,并注入SideBarController

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

【问题讨论】:

    标签: c# dependency-injection ninject


    【解决方案1】:

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

    当定义和指定路由键时返回 true,routeValue 等于路由键的路由值或为 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();
    }
    

    【讨论】:

    • 这看起来让我走上了正轨,谢谢。我现在需要的是一种方式来表达“如果上下文绑定不匹配,则将 IService 绑定到 BasicService。”
    • 不建议在运行时使用Rebind。看到这个:stackoverflow.com/a/9209932/1193333。我肯定会选择 @Remo 。相反,只需创建默认绑定,没有 When 条件。 Ninject 首先尝试解析When 条件,如果全部失败,则进行默认绑定。请参阅我的更新答案。
    • 有趣;我不认为我能早点让它工作,但我会再试一次。感谢您更新您的答案。
    • 刚刚又试了一次,我是对的。如果使用您提出的解决方案,我会收到带有消息“多个匹配的绑定可用。”的ActivationException:它可以解析为全部绑定上的 DefaultService,或在适当的上下文绑定上匹配的特定服务. (忍者 3.0)
    • 刚刚安装了带有 Ninject 3 的 asp-mvc 3,它按预期工作。确保不能同时满足多个条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    相关资源
    最近更新 更多