将属性注入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

将属性注入web api过滤器Autofac

属性根本不是di友好的。它们是由。net框架实例化的,因此您无法控制它们的依赖关系。因此,最好的解决方案是完全放弃使用ActionFilterAttribute的想法。

正如被动属性中指出的,您可以将ActionFilterAttribute分解为2个继承特性:

  1. Attribute子类(不包含任何行为)
  2. 一个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实例中有一些适用于当前请求的状态。如果不是这种情况,那么您可以按原样使用此代码。

另一方面,如果您的对象是有状态的,那么您可以使用以下方法之一在运行时解析它:
  1. 注入一个抽象工厂来创建你的MyClass实例,而不是直接注入类到过滤器中。
  2. 在过滤器中注入一个Func<Type, IMyClass>,以便在你的组合根中调用一个匿名方法,该方法使用容器来解析实例,如下所示。

您是否按照AutoFac文档中描述的步骤为属性使用IoC ?

为动作过滤器启用属性注入

在构建容器并将其提供给AutofacDependencyResolver之前,在ContainerBuilder上调用RegisterFilterProvider()方法来使用过滤器属性注入。

builder.RegisterFilterProvider();

通过阅读文档和查看本网站的其他示例,例如:

autofac-attribute-injection和如何使用autofac属性注入,似乎你需要的是:

builder.RegisterType<IMyclass>().As<MyClass>().InstancePerRequest();
builder.RegisterType<Action1DebugActionWebApiFilter>().PropertiesAutowired();