Как сделать инъекцию действия для MVC 3 с помощью Autofac?



Я создаю ASP.NET приложение MVC 3 пытается воспользоваться впрыском действия контроллера, как описано здесь .



Инъекция конструктора контроллера работает без каких-либо проблем, но я не могу заставить инъекцию действия работать.



Я настроил Autofac в Global.asax вот так:





var builder = new ContainerBuilder();

builder.Register<ITestInject>(c => new TestInject { TestString = "hi" });

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterControllers(typeof(MvcApplication).Assembly).InjectActionInvoker();

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


И мой контроллер имеет такое действие:





public ActionResult Test(ITestInject testInject)
{
return View(testInject);
}


Класс/интерфейс TestInject/ITestInject определяется следующим образом:





public interface ITestInject
{
string TestString { get; }
}
public class TestInject : ITestInject
{
public string TestString { get; set; }
}


Когда я пытаюсь перейдите к действию тест, я вижу эту ошибку:




Ошибка сервера в приложении"/".



невозможно создать экземпляр интерфейса.



Описание: необработанное исключение возникло во время выполнения текущего веб-запроса. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.



Детали Исключения: Система.MissingMethodException: не удается создать экземпляр взаимодействие.



Ошибка Источника:



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



Трассировка Стека:



[MissingMethodException: Cannot create an instance of an interface.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +199
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +572
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +449
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +317
Autofac.Integration.Mvc.ExtensibleActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +122
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +117
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c_DisplayClassb.<BeginProcessRequest>b_5() +37
System.Web.Mvc.Async.<>c_DisplayClass1.<MakeVoidDelegate>b_0() +21
System.Web.Mvc.Async.<>c_DisplayClass8`1.<BeginSynchronous>b_7(IAsyncResult ) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c
_DisplayClasse.<EndProcessRequest>b_d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b
_0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184


Сведения о версии: Microsoft .NET Framework версия: 4.0.30319; ASP.NET версия: 4.0.30319.1




Какие-нибудь идеи о том, что я делаю неправильно здесь?



Я использую Autofac версии 2.4.5.724.



Спасибо.

528   2  

2 ответов:

Впрыск действия выключен по умолчанию в текущей реализации Autofac MVC3.

Чтобы включить его, передайте параметр в ExtensibleActionInvoker:

builder.RegisterType<ExtensibleActionInvoker>()
    .As<IActionInvoker>()
    .WithParameter("injectActionMethodParameters", true);

Это было совсем недавнее изменение, и некоторые документы нуждаются в обновлении-извините за хлопоты.

Проблема в этой строке

builder.Register<ITestInject>(c => new TestInject { TestString = "hi" });

Первым параметром в любом методе Register являетсяконкретный сервис , который вы хотите зарегистрировать. За этим типом следует "как создать экземпляр", а затем параметры, определяющие фактический интерфейс для предоставления сервиса в качестве. Вы получаете исключение, потому что Autofac пытается создать экземпляр реализации, которая в приведенном выше случае является интерфейсом. Очевидно, что никакой конструктор не найден на интерфейсном типе.

Теперь посмотрите на это:

builder.Register<TestInject>(c => new TestInject { TestString = "hi" }).As<ITestInject>();

Этот подход IMO является одной из сильных сторон Autofacs по сравнению с другими системами DI. Там, где другие начинают регистрацию с интерфейса, который вы хотите предоставить, и заканчивают реализацией, Autofac начинается с фактической реализации и заканчивается интерфейсом. Это делает синтаксис более чистым, особенно в тех случаях, когда одна конкретная реализация может быть представлена в виде нескольких интерфейсов, все в одной регистрации.

Comments

    Ничего не найдено.