代码改变世界

过滤器注入问题

  huoit  阅读(724)  评论(1编辑  收藏  举报

过滤器概要

1、过滤器工作顺序

中间件重在影响管道,过滤器重在请求与响应数据交互的环节,如验证错误路由等

2、作用域

三种:Controller、Action、全局;前两种直接加特性就可以了

全局:startup

复制代码
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(SampleActionFilter)); // by type
        options.Filters.Add(new SampleGlobalActionFilter()); // an instance
    });

    services.AddScoped<AddHeaderFilterWithDi>();
}
复制代码

 

3、同步异步

IAsyncActionFilter和IActionFilter;同一个过滤器只能有一种选择,要么同步要么异步,系统会首先检查异步,没有则走同步

 

public async Task OnActionExecutionAsync

 

 

依赖注入两种方法

方法一:使用TypeFilterAttribute或者ServiceFilterAttribute

1、TypeFilterAttribute使用Microsoft.Extensions.DependencyInjection.ObjectFactory实例化类型

复制代码
public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
    private ObjectFactory factory;

    public TypeFilterAttribute([NotNull] Type type)
    {
        ImplementationType = type;
    }

    public object[] Arguments { get; set; }

    public Type ImplementationType { get; private set; }

    public int Order { get; set; }

    public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
    {
        if (this.factory == null)
        {
            var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray();

            this.factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes);
        }

        return (IFilter)this.factory(serviceProvider, Arguments);
    }
}
复制代码

使用:

[TypeFilter(typeof(AddHeaderAttribute),
    Arguments = new object[] { "Author", "Steve Smith (@ardalis)" })]
public IActionResult Hi(string name)
{
    return Content($"Hi {name}");
}

2、ServiceFilterAttribute则是暴露IFilterFactory接口,通过系统的DI系统注入,所以需要2个步骤

源码

复制代码
public class ServiceFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
    public ServiceFilterAttribute([NotNull] Type type)
    {
        ServiceType = type;
    }

    public Type ServiceType { get; private set; }

    public int Order { get; set; }

    public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
    {
        var service = serviceProvider.GetRequiredService(ServiceType);

        var filter = service as IFilter;
        if (filter == null)
        {
            throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
                typeof(ServiceFilterAttribute).Name,
                typeof(IFilter).Name));
        }

        return filter;
    }
}
复制代码

使用

services.AddScoped<AddHeaderFilterWithDi>();//放入startup才可以使用

[ServiceFilter(typeof(AddHeaderFilterWithDi))]

 

 

方法二:自定义依赖注入辅助类

复制代码
    public static class IoC
    {
        public static IServiceCollection ServiceCollection { get; set; }
        private static ServiceProvider ServiceProvider { get; set; }

        public static void InitializeWith(IServiceCollection serviceDescriptors)
        {
            ServiceCollection = serviceDescriptors;
            ServiceProvider = ServiceCollection.BuildServiceProvider();
        }

        public static void InitializeWith(IServiceCollection serviceDescriptors, IServiceProvider serviceProvider)
        {
            ServiceCollection = serviceDescriptors;
            ServiceProvider = (ServiceProvider)serviceProvider;
        }

        public static bool IsExist()
        {
            return ServiceCollection != null;
        }

        public static T Resolve<T>()
        {
            return ServiceProvider.GetService<T>();
        }

        public static IEnumerable<T> ResolveAll<T>()
        {
            return ServiceProvider.GetServices<T>();
        }

        public static void Reset()
        {
            if (ServiceCollection != null)
            {
                ServiceCollection.Clear();
                ServiceProvider.Dispose();
            }
        }
    }
自定义依赖注入辅助类
复制代码

 

再startup中初始化

public void ConfigureServices(IServiceCollection services)
        {
            
           services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddCors();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            IoC.InitializeWith(services);
        }

 

 

 

 

 

 

 

 

 

资料:

https://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_4_3-filters.html

 

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示