2011-01-18 3 views
3

Я довольно новыми для DI с Autofac и интересно, если возможно следующееMVC контроллер Generic инъекции с AutoFac

Я хочу создать универсальный контроллер и действие, который принимает впрыскивается типа. Мне не нужен экземпляр введенного типа, но просто нужен его тип , который будет реализовывать ожидаемый интерфейс.

Я также хотел бы передать этот общий тип на ViewModel, но это совсем другая тема, однако, если какой-нибудь гениальный там может решить, то это будет отлично.

public ContractorController<T> : Controller 
    where T : IContractor{ 

    public ViewResult New() { 
      var vNewModel = new NewViewModel<T>(); 
      return View(vNewModel); 
     } 
} 

Этот контроллер должен быть вызван через http://mysite.com/Contractor/New

Я смотрел в регистрации генериков с AutoFac, но кажется, что проблема заключается в том, что AutofacControllerFactory реализует только GetControllerInstance(), ожидая типа контроллера передается ему из GetController() или CreateController(), не уверен, что или что между ними существует различие. Эти методы получают имя контроллера как строку из RoutData и возвращают соответствующий тип .NET, который дает url, http://mysite.com/Contractor/New является контроллером = Подрядчик, и, таким образом, ContractorController не может быть сопоставлен с GetController() или CreateController(), и перед этим передается значение null в GetControllerInstance (), что означает, что AutofacControllerFactory не пытается разрешить тип.

я понял, что я должен был бы создать собственный контроллер Factory производных от AutofacControllerFactory, переопределить GetController() или CreateController() и выполнить свое собственное отображение из имен контроллеров в общие тип. Что-то вроде

если (controllerName == "Подрядчик") возвращение System.Type.GetType ( + controllerName + "Controller`1" "UI.Controllers.");

Когда я отлаживаю это, я вижу, что этот код находит общий контроллер и возвращает его.

Я думал, что я мог бы просто зарегистрировать типы как

builder.RegisterType<FakeContractor>().As<IContractor>(); 
builder.RegisterGeneric(typeof(ContractorController<>)); 

Но я получаю следующее сообщение об ошибке

The Autofac service 
'UI.Controllers.ContractorController`1' 
representing controller 
'ContractorManagement.UI.Controllers.ContractorController`1' 
in path '/Contractor/New' has not been registered. 

Так что я думаю, что я может быть ложным дерево. Может кто-нибудь, пожалуйста, пролить некоторый свет на то, как я могу сделать это без потянув зубы

Спасибо

ответ

0

Я не совсем уверен, почему вы хотите контроллер, используя общий. Использование генератора на контроллере в Mvc на самом деле не поддерживается - или, по крайней мере, будет задействован поддерживающий путь маршрутизации. Возможно, вы можете предоставить больше информации о причинах подхода?

Похоже, что вам нужен контроллер, который поддерживает привязку модели к различным типам. Следующий вопрос заключается в том, варьируются ли эти типы в общем интерфейсе или базовом классе.

Если это так, для Mvc2 проверьте the IocModelBinder information. Это будет хорошо работать с Autofac.Это позволит типу модели быть привязанным к сообщению или получить возможность вводить услуги с помощью autofac.

Если вы хотите изменить типы с помощью общего основания, поддерживающего разнообразную модель конкретного вида, а затем проверьте the DerivedTypeModelBinder in MvcContrib. Существует версия, которая работает в Mvc 1, 2, и теперь MvcContrib для Mvc3 имеет хорошее примерное приложение для сопровождения. Реализация Mvc3 также быстрее - скорость не была проблемой раньше, это всего лишь более эффективный процесс идентификации.

0

Может быть, это не прямой ответ на ваш вопрос, но это единственный возможный способ использовать общие контроллеры, которые я когда-либо видел и использовал:

public abstract class ContractorControllerBase<T> : Controller where T : IContractor { 
    public ViewResult New() { 
     var vNewModel = new NewViewModel<T>(); 
     return View(vNewModel); 
    } 
} 

public class FakeContractorController : ContractorControllerBase<FakeContractor> { 
} 
Смежные вопросы