2013-02-11 3 views
3

У меня необычная ситуация, в которой вы вводите службу в ASP.NET MVC Controller. Контроллер обеспечивает одно действие для отображения меню боковой панели на странице, а служба, введенная в контроллер, является фабрикой для создания содержимого боковой панели. Действие украшено атрибутом [ChildActionOnly]: боковая панель может отображаться только при рендеринге другого действия.Ninject Контекстное связывание по запросу MVC

Трудность заключается в том, что я хочу ввести разные экземпляры абстракции фабрики боковой панели в соответствии с запрошенной страницей (= Контроллер). Раньше я делал это с использованием своего рода абстрактной фабрики, которая имела неэлегантную реализацию использования строки имени контроллера, чтобы определить, какую конкретную заводскую реализацию использовать; Теперь я перевел это на надлежащую абстрактную фабрику и, следовательно, вам нужно переместить выбор типа фабрики в другом месте.

Моего 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

Я консультировался вики страница Ninject на Contextual Binding, который, как представляется, является то, что я хочу в принципе, но я не нашел там ничего документированного, которое ob яростно добиваюсь своей цели.

ответ

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() метод

Возвращает 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(); 
} 
+0

Это похоже на то, чтобы получить меня на правильном пути, спасибо. Теперь мне нужен способ сказать «Привязать IService к BasicService, если контекстные привязки не совпадают.« – alastairs

+0

Kernel.Rebind () - это путь. Сортировка, спасибо! – alastairs

+0

Не рекомендуется использовать' Rebind' во время выполнения. См. Это: http://stackoverflow.com/a/9209932/1193333. И я будет определенно идти с @Remo. Вместо этого просто создайте привязку по умолчанию без условия «Когда». Сначала Ninject пытается разрешить условия «Когда», и если все не удается, тогда оно идет по умолчанию. См. мой обновленный ответ. – mipe34

Смежные вопросы