我有一个小过滤器
public class Action1DebugActionWebApiFilter : ActionFilterAttribute
{
public IMyclass myClass { get; set; }
public override void OnActionExecuting(HttpActionContext actionContext)
{
// pre-processing
Debug.WriteLine("ACTION 1 DEBUG pre-processing logging");
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
if (objectContent != null)
{
var type = objectContent.ObjectType; //type of the returned object
var value = objectContent.Value; //holding the returned value
}
Debug.WriteLine("ACTION 1 DEBUG OnActionExecuted Response " + actionExecutedContext.Response.StatusCode.ToString());
}
}
我希望 IMyclass 注入(inject)一个从 AutoFac 解析的类。
builder.RegisterType<IMyclass >().As<MyClass>().InstancePerRequest();
然而它仍然是null。我的所有其他注入(inject)在构造函数中都工作正常,但在属性中却没有。
请您参考如下方法:
属性根本不是 DI 友好的。它们由 .NET 框架实例化,因此您无法控制它们具有的依赖项。所以,最好的解决办法就是放弃使用ActionFilterAttribute的想法。完全。
正如 passive attributes 中指出的那样, 你可以分解你的 ActionFilterAttribute进入它的 2 个继承特性:
- 安
Attribute子类(不包含任何行为)。 - DI 友好
IActionFilter子类(使用构造函数注入(inject))。
Action1DebugAttribute
首先,有一个属性来标记您的 Controller 和操作。此属性根本不包含任何行为(但如果需要,它可能包含类似 this example 的属性)。
// This attribute should contain no behavior. No behavior, nothing needs to be injected.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class Action1DebugAttribute : Attribute
{}
Action1DebugActionWebApiFilter
这是 DI 友好的 Action 过滤器。如果需要,我们可以使用构造函数注入(inject)或属性注入(inject)。为了简单起见,此示例使用构造函数注入(inject)。
public class Action1DebugActionWebApiFilter : IActionFilter
{
private readonly IMyclass myClass;
public Action1DebugActionWebApiFilter(IMyClass myClass)
{
if (myClass == null)
throw new ArgumentNullException("myClass");
this.myClass = myClass;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (this.IsFilterDefined(actionContext.ActionDescriptor))
{
// pre-processing
Debug.WriteLine("ACTION 1 DEBUG pre-processing logging");
}
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
if (this.IsFilterDefined(actionExecutedContext.ActionDescriptor))
{
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
if (objectContent != null)
{
var type = objectContent.ObjectType; //type of the returned object
var value = objectContent.Value; //holding the returned value
}
Debug.WriteLine("ACTION 1 DEBUG OnActionExecuted Response " + actionExecutedContext.Response.StatusCode.ToString());
}
}
private bool IsFilterDefined(ActionDescriptor actionDescriptor)
{
return actionDescriptor.IsDefined(typeof(Action1DebugAttribute), inherit: true)
|| actionDescriptor.ControllerDescriptor.IsDefined(typeof(Action1DebugAttribute), inherit: true);
}
}
用法
完成此操作后,您可以简单地使用 Autofac 来解析您的操作过滤器及其在组合根中的所有依赖项。
注册
builder.RegisterType<IMyclass>().As<MyClass>();
// Since it is possible more than one `IActionFilter` is registered,
// we are using a named type. You could alternatively create another
// interface to uniquely identify this action filter.
builder.RegisterType<IActionFilter>()
.Named<Action1DebugActionWebApiFilter>("action1DebugActionWebApiFilter");
正在解决
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters, IContainer container)
{
filters.Add(container.ResolveNamed<IActionFilter>("action1DebugActionWebApiFilter"));
filters.Add(new HandleErrorAttribute());
}
}
生命周期
您将无法在每个请求生命周期内使用实例,因为操作过滤器是作为 MVC 对象图的一部分创建的,而不是根据请求解析。
但是,您这样做的愿望表明 IMyClass实例中有一些适用于当前请求的状态。如果不是这种情况,那么您可以按原样使用此代码。
另一方面,如果您的对象是有状态的,那么您可以使用以下方法之一在运行时解析它:
- 注入(inject) Abstract Factory创建你的
MyClass实例而不是将类直接注入(inject)过滤器。 - 注入(inject)
Func<Type, IMyClass>进入过滤器以调用组合根内部的匿名方法,该方法使用容器来解析实例 as shown here .
