我有一个小过滤器
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
。我所有的其他注射在构造函数中都能正常工作,但在属性中却没有。
答案 0 :(得分:3)
属性根本不是DI友好的。它们由.NET框架实例化,因此您无法控制它们具有哪些依赖项。因此,最好的解决方案是放弃完全使用ActionFilterAttribute
的想法。
正如passive attributes所指出的那样,您可以将ActionFilterAttribute
细分为2个继承的功能:
Attribute
子类(不包含任何行为)。IActionFilter
子类(使用构造函数注入)。首先,有一个属性用于标记您的控制器和操作。此属性根本不包含任何行为(但如果需要,它可能包含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
{}
这是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);
}
}
执行此操作后,您只需使用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
实例中有一些适用于当前请求的状态。如果不是这样,那么您可以按原样使用此代码。
另一方面,如果您的对象是有状态的,那么您可以使用以下方法之一在运行时解决它:
MyClass
实例的Abstract Factory,而不是直接将类注入过滤器。Func<Type, IMyClass>
注入过滤器,以便在使用容器解析实例as shown here的合成根内部调用匿名方法。答案 1 :(得分:0)
阅读文档并查看本网站上的其他示例,例如:
autofac-attribute-injection和 how to use property injection with autofac,您似乎需要的是:
builder.RegisterType<IMyclass>().As<MyClass>().InstancePerRequest();
builder.RegisterType<Action1DebugActionWebApiFilter>().PropertiesAutowired();
答案 2 :(得分:0)
您是否按照AutoFac documentation中描述的步骤使用IoC进行属性?
为操作过滤器启用属性注入
要为您的过滤器属性使用属性注入,请在构建容器并将其提供给
RegisterFilterProvider()
之前调用ContainerBuilder
上的AutofacDependencyResolver
方法。builder.RegisterFilterProvider();