一种方法是从属性中删除逻辑并在实现 IActionFilter 的类中实现它。然后将该类注册到容器中,以便依赖注入能够正常工作。Orchard CMS 使用这种方法。
public class MyCustomActionFilterAttribute : Attribute
{
}
public class MyCustomActionFilter : FilterProvider, IActionFilter
{
protected MyService Service { get; private set; }
// MyService can be injected by the container...
public MyCustomActionFilter(MyService service)
{
this.Service = service;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check to see if the action has a matching attribute
var attributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MyCustomActionFilterAttribute), true);
// Perform some logic here....
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
可以创建一个将过滤器应用于操作的 IActionInvoker,此类使用 DependencyResolver 自动实例化我的 MVC。
public class FilterResolvingActionInvoker : ControllerActionInvoker
{
protected IEnumerable<IFilterProvider> Providers { get; private set; }
// Filters registered with the container are injected by the container
public FilterResolvingActionInvoker(IEnumerable<IFilterProvider> providers)
{
this.Providers = providers;
}
// Add the filter to the current FilterInfo
protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(controllerContext, actionDescriptor);
foreach (var provider in this.Providers)
{
provider.AddFilters(filters);
}
return filters;
}
}
定义一个允许我们注册过滤器的通用接口。
public interface IFilterProvider
{
void AddFilters(FilterInfo filterInfo);
}
public abstract class FilterProvider : IFilterProvider
{
public void AddFilters(FilterInfo filterInfo)
{
if (this is IActionFilter)
{
filterInfo.ActionFilters.Add(this as IActionFilter);
}
}
}
并将它们注册到容器构建器。也可以为 Autofac 创建一个扩展方法,以在您的程序集中自动注册所有 IFilterProviders。
builder.RegisterType<FilterResolvingActionInvoker>().As<IActionInvoker>().InstancePerDependency();
builder.RegisterType<MyCustomActionFilter>().As<IFilterProvider>().InstancePerDependency();