将属性注入web api过滤器Autofac
本文关键字:过滤器 Autofac api web 属性 注入 | 更新日期: 2023-09-27 18:15:36
我有一个小过滤器
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
注入一个类,从AutoFac解析。
builder.RegisterType<IMyclass >().As<MyClass>().InstancePerRequest();
仍然是null
。
属性根本不是di友好的。它们是由。net框架实例化的,因此您无法控制它们的依赖关系。因此,最好的解决方案是完全放弃使用ActionFilterAttribute
的想法。
正如被动属性中指出的,您可以将ActionFilterAttribute
分解为2个继承特性:
-
Attribute
子类(不包含任何行为) - 一个di友好的
IActionFilter
子类(使用构造函数注入)。
Action1DebugAttribute
首先,有一个用来标记控制器和操作的属性。这个属性根本不包含任何行为(但如果需要,它可能包含像这个例子中的属性)。
// 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友好的动作过滤器。如果需要,我们可以使用构造函数注入或属性注入。为了简单起见,本例使用构造函数注入。
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);
}
}
使用一旦你这样做了,你就可以简单地使用autofacc来解析你的动作过滤器和它在你的合成根中的所有依赖项。
登记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
实例中有一些适用于当前请求的状态。如果不是这种情况,那么您可以按原样使用此代码。
- 注入一个抽象工厂来创建你的
MyClass
实例,而不是直接注入类到过滤器中。 - 在过滤器中注入一个
Func<Type, IMyClass>
,以便在你的组合根中调用一个匿名方法,该方法使用容器来解析实例,如下所示。
您是否按照AutoFac文档中描述的步骤为属性使用IoC ?
为动作过滤器启用属性注入
在构建容器并将其提供给
AutofacDependencyResolver
之前,在ContainerBuilder
上调用RegisterFilterProvider()
方法来使用过滤器属性注入。builder.RegisterFilterProvider();
通过阅读文档和查看本网站的其他示例,例如:
autofac-attribute-injection和如何使用autofac属性注入,似乎你需要的是:
builder.RegisterType<IMyclass>().As<MyClass>().InstancePerRequest();
builder.RegisterType<Action1DebugActionWebApiFilter>().PropertiesAutowired();