我面临的问题是AutoFac不会将预期参数注入相应的过滤器。
我有一个过滤器,用于记录所有控制器中所有方法的执行持续时间。为了完成这项任务,我创建了一个像这样的ActionFilter:
//... other usings here...
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace MyNamespace
{
internal class ExecutionTimeFilter : ActionFilterAttribute
{
public Logger _logger { get; set; }
public ExecutionTimeFilter(Logger logger)
{
_logger = logger;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
_logger.Log("Log the starting time + controller + action + etc");
actionContext.Request.Properties["Stopwatch"] = Stopwatch.StartNew();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var stopwatch = (Stopwatch)actionExecutedContext.Request.Properties["Stopwatch"];
_logger.Log("Log the stopwatch.ElapsedMilliseconds + controller + action + etc");
}
}
}
我正在注册我的依赖项,如下所示:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
var container = new IocConfiguration().Configure(GlobalConfiguration.Configuration);
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
//This is the only way I can get the logger injected
//This is what ideally I want to avoid
GlobalConfiguration.Configuration.Filters.Add(new ExecutionTimeFilter(_logger));
}
//IocConfiguration
using Autofac;
using Autofac.Integration.WebApi;
using System.Reflection;
using System.Web.Http;
using System.Web.Mvc;
namespace MyNamespace
{
internal class IocConfiguration
{
public IContainer Configure(HttpConfiguration httpConfiguration)
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(LogManager.GetLogger("LoggerName")).As<Logger>().SingleInstance();
builder.RegisterWebApiFilterProvider(httpConfiguration);
return builder.Build();
}
}
}
如果我按照official site中描述的步骤操作,我会收到代码段后面描述的错误:
var builder = new ContainerBuilder();
builder.Register(c => new ExecutionTimeFilter(c.Resolve<Logger>()))
.AsWebApiActionFilterFor<MyController>()
.InstancePerRequest();
类型&#39; MyController&#39;必须可分配给 &#39; Autofac.Integration.WebApi.IAutofacActionFilter&#39 ;.参数名称: 注册
以下是控制器的摘录:
//...Other usings...
using System.Threading.Tasks;
using System.Web.Http;
using System;
namespace MyNamespace.Controllers
{
public class MyController : ApiController
{
private readonly Logger _logger;
public MarketoController(Logger logger)
{
_logger = logger;
}
}
[HttpGet]
[Route("path/{entityId}")]
[ValidateEntityId]
public async Task<IHttpActionResult> Get(int? entityId = null)
{
return Ok();
}
}
我错过了什么?
答案 0 :(得分:2)
我发现您的过滤器ExecutionTimeFilter
继承自ActionFilterAttribute
。 If you notice in the docs Autofac过滤器机制不使用Web API操作过滤器接口。
异常消息有些令人困惑,但我猜测问题是您在注册中尝试使用Web API属性过滤器,希望您使用Autofac过滤器接口。
您可能在文档中遗漏的关键步骤是第二步:
您的类不是从现有的Web API过滤器属性派生,而是实现集成中定义的适当过滤器接口。下面的过滤器是一个操作过滤器,实现
IAutofacActionFilter
而不是System.Web.Http.Filters.IActionFilter
。
我在那里最重要的地方添加了一些大胆的内容。
文档归结为:
Register(...).AsWebApiActionFilterFor<T>()
内容,则需要使用Autofac过滤器接口。文档中详细解释了为什么Autofac使用自定义界面以及为什么DI不能使用标准过滤器。