如何在Ninject中创建基于所请求的控制器更改的绑定?

时间:2012-07-22 22:29:08

标签: asp.net-mvc dependency-injection ninject asp.net-mvc-4

我有一个ASP.NET MVC 3应用程序,并遇到以下情况。在我的页面上,我有一个侧栏,可以包含特定于该页面的相关链接,即由控制器类型确定。链接将由当前页面的内容确定。

我使用Html.Action和一个单独的控制器跟踪Phil Haack's blog post渲染动态边栏。我喜欢这种方法给我的关注点分离:我的控制器根本不了解侧栏,这应该是它的方式。

我现在想要将SideBar的派生类型的实例注入到我的SideBarController中,将调用该动作来呈现侧栏本身。每个控制器有一个派生类型SideBar,所以我发现自己想要编写类似于此的代码:

kernel.Bind<SideBar>().ToMethod(_ => controllerName == "foo" 
                                         ? new FooSideBar(kernel.Get<UrlHelper>()) 
                                         : new BarSideBar(kernel.Get<UrlHelper>()));

但是代码片段有很多错误,尤其是我无法掌握lambda中的控制器名称,以及第三种类型的控制器出现时会发生什么的问题,然后是第四个,等等。

请注意,我无法使用WhenInjectedInto<T>(),因为SideBar实例将始终注入SideBarController

对于它的价值,SideBar的实例目前正在通过Ninject Factory扩展创建,因此相关的侧栏绑定如下(我已经硬化了SideBar的实现,只是为了证明到目前为止的方法工作):

kernel.Bind<ISideBarFactory>().ToFactory().InRequestScope();
kernel.Bind<SideBar>().To<FooSideBar>().InRequestScope();

最后,我基本上在派生类型SideBar和控制器类型之间进行了一对一的映射。感觉有点像这里可能有一些重复,但它也代表了组件之间的关系,所以我觉得我很好。

这一切让我觉得我对这部分问题的解决方法是错误的,所以我欢迎有关如何使用Ninject实现清洁解决方案的建议。

3 个答案:

答案 0 :(得分:3)

我会好好回答,但我现在不在电脑附近,所以它会有点模糊。

从根本上说,您可以将另一个参数传递给Html.Action,因此如果该参数是请求或从请求中收集的内容(例如控制器名称或Url部分),那么您可以使用它来确定要显示的侧边栏。您可能需要将工厂注入侧边栏控制器,并使用它来创建正确的控制器,或其他一些摆弄,但一旦您知道需要哪个侧边栏,它就会变得更容易。

答案 1 :(得分:1)

我不确定使用ninject是否可行,但是它正在使用ModelBinding:

public interface ISidebar
    {
    }
    public class Sidebar1 : ISidebar
    {
    }
    public class Sidebar2 : ISidebar
    {
    }


 public class SidebarModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var controller = controllerContext.RouteData.Values["Controller"];
            var action = controllerContext.RouteData.Values["Action"];

            switch (controller.ToString())
            {
                case "Home":
                    return new Sidebar1();

                default:
                    return new Sidebar2();

            }

            throw new NotImplementedException();
        }
    }


 public class TestController : Controller
    {
        public TestController()
        {
        }

        public string Index(ISidebar sidebar)
        {
            //Do something with it
            return "OK";
        }
    }

//Add to the Application_Start
ModelBinders.Binders.Add(typeof(ISidebar), new SidebarModelBinder());
编辑:花了一段时间,但设法使用Ninject让它工作。

请阅读:http://blog.voltje.be/2012/08/22/creating-a-dynamic-sidebar-with-asp-net-mvc-ninject/

答案 2 :(得分:0)

建议:

  • 不要注入侧边栏。
  • 而是注入[sidebar] ContentProvider。
  • 在全局asax(每个请求)中绑定默认实现,然后在控制器中解除绑定并重新绑定(如果需要)。