1 つの方法は、Attribute からロジックを削除し、IActionFilter を実装するクラスに実装することです。次に、依存性注入が正しく機能するように、クラスがコンテナーに登録されます。このアプローチを使用するオーチャード 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 の拡張メソッドを作成して、アセンブリ内のすべての IFilterProvider を自動的に登録することもできます。
builder.RegisterType<FilterResolvingActionInvoker>().As<IActionInvoker>().InstancePerDependency();
builder.RegisterType<MyCustomActionFilter>().As<IFilterProvider>().InstancePerDependency();