2011-03-23 19 views
2

我正在创建一个试图利用控制器动作注入的ASP.NET MVC 3应用程序,如here所述。如何使用Autofac为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; } 
} 

当我尝试导航到测试动作,我看到这个错误:对,我做错了什么在这里

Server Error in '/' Application.

Cannot create an instance of an interface.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: Cannot create an instance of an interface.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

 
[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 

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1

任何想法?

我正在使用Autofac版本2.4.5.724。

谢谢。

回答

7

在当前的Autofac MVC3实现中默认关闭动作注入。

要启用它,参数传递给ExtensibleActionInvoker

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

这是相当近期的变化和一些文档需要更新 - 有关的麻烦遗憾。

+0

哦,我的,它的工作!谢谢! – 2011-03-25 13:12:31

0

问题是此行

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

任何Register的第一个参数是你要注册的具体的服务。在该类型之后是“如何实例化”,然后是定义实际接口以将服务公开为的参数。你会得到这个异常,因为Autofac试图实例化实现,在上面的例子中是一个接口。显然,在接口类型中找不到构造函数。

现在看看这个:

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

这种做法IMO是相对于其他DI框架Autofacs强项之一。在其他人开始注册您想要公开的接口并结束实施的情况下,Autofac将从实际实施开始,并以接口结束。这使得语法更清晰,特别是在一个具体实现可以作为多个接口公开的情况下,全部在一个注册中。

+0

在这种情况下并非如此 - 泛型参数类型在大多数情况下被忽略,应该被排除。 – 2011-03-25 04:10:08

+0

Ahhrg,假设仍然是所有失败的母亲:) – 2011-03-25 07:26:35

+0

我听到雅,每次仍然让我:) – 2011-03-25 08:45:56