.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

Posted 追逐时光者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法相关的知识,希望对你有一定的参考价值。

前言

  前段时间有朋友问道一个这样的问题,.NET Core中如何通过Attribute的元数据信息来调用标记的对应方法。我第一时间想到的就是通过C#反射获取带有Custom Attribute标记的类,然后通过依赖注入(DI)的方式获取对应服务的方法并通过反射动态执行类的方法,从而实现更灵活的编程方式。

C#中反射指的是什么?

开篇之前首先和大家简单介绍一下反射的概念和作用。

在 C# 中,反射是指在运行时动态地获取类型的信息并操作对象的能力。使用反射,我们可以在代码中访问程序集、模块、成员等,并且可以操作这些成员的属性、方法、字段和事件等。

自定义一个Attribute类型

/// <summary>
/// 自定义一个Attribute类型
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CustomAttribute : Attribute

    public string TargetMethod  get; set; 

    public CustomAttribute(string targetMethod)
    
        TargetMethod = targetMethod;
    

定义如下两个需要被执行的服务,并使用CustomAttribute标记

/// <summary>
/// 前进服务
/// </summary>
[Custom("AdvanceWay")]
public class AdvanceService

    public void AdvanceWay()
    
        Console.WriteLine("On the move!");
    


/// <summary>
/// 后退服务
/// </summary>
[Custom("RetreatWay")]
public class RetreatService

    public void RetreatWay()
    
        Console.WriteLine("Be retreating!");
    

注册需要注入的服务

var services = new ServiceCollection();

//注册需要注入的服务
services.AddTransient<AdvanceService>();
services.AddTransient<RetreatService>();

反射获取所有带有CustomAttribute特性的类并调用对应方法

    static void Main(string[] args)
    
        var services = new ServiceCollection();

        //注册需要注入的服务
        services.AddTransient<AdvanceService>();
        services.AddTransient<RetreatService>();

        var provider = services.BuildServiceProvider();

        #region 反射获取所有带有CustomAttribute特性的类并调用对应方法

        //反射获取所有带有CustomAttribute特性的类
        var classes = Assembly.GetExecutingAssembly().GetTypes()
            .Where(type => type.GetCustomAttributes<CustomAttribute>().Any());

        foreach (var clazz in classes)
        
            //获取标记CustomAttribute的实例
            var attr = clazz.GetCustomAttributes<CustomAttribute>().First();

            //根据CustomAttribute元数据信息调用对应的方法
            var methodInfo = clazz.GetMethod(attr.TargetMethod);
            if (methodInfo != null)
            
                //instance 对象是通过依赖注入容器获取的。这是一种常用的实现方式,可以使用依赖注入解耦程序中各个组件之间的依赖关系,方便测试和维护。
                var instance = provider.GetService(clazz);
                methodInfo.Invoke(instance, null);
            
        

        #endregion

        #region 反射获取所有带有CustomAttribute特性的类并调用指定方法

        var executionMethod = "RetreatWay";

        foreach (var clazz in classes)
        
            //获取标记CustomAttribute的实例
            var attr = clazz.GetCustomAttributes<CustomAttribute>().First();

            if (attr.TargetMethod == executionMethod)
            
                //根据CustomAttribute元数据信息调用对应的方法
                var methodInfo = clazz.GetMethod(attr.TargetMethod);
                if (methodInfo != null)
                
                    //instance 对象是通过依赖注入容器获取的。这是一种常用的实现方式,可以使用依赖注入解耦程序中各个组件之间的依赖关系,方便测试和维护。
                    var instance = provider.GetService(clazz);
                    methodInfo.Invoke(instance, null);
                
            
        

        #endregion

        Console.ReadLine();
    

输出如下:

 

带有取消令牌的自定义 ASP.NET Core 中间件

【中文标题】带有取消令牌的自定义 ASP.NET Core 中间件【英文标题】:Custom ASP.NET Core Middleware with cancellation Token 【发布时间】:2016-11-01 02:24:44 【问题描述】:

我有一个自定义 ASP.NET Core 中间件,我想检索请求的取消令牌。

我尝试将它添加到调用的签名中,如下所示:

public async Task Invoke(HttpContext context,CancellationToken token)

但是一旦我添加它,它就不再被调用了。

我做错了什么?

【问题讨论】:

【参考方案1】:

我认为这个想法是不能从中间件内部取消中间件的调用,如果您调用一些接受取消令牌的异步任务,那么您可以创建一个并将其传递给您从内部调用的内容在那里。

如果请求中止,常见的情况是取消任务,因此您可以像这样创建令牌:

CancellationToken CancellationToken => context?.RequestAborted ?? CancellationToken.None;

然后调用一些异步服务,比如获取数据或查询数据库,如果请求被中止,那么取消请求应该发生

【讨论】:

以上是关于.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法的主要内容,如果未能解决你的问题,请参考以下文章

c# -反射获取自定义特性

学习--反射

ASP.NET Core 中如何通过 AuthorizeAttribute 做自定义验证?

带有取消令牌的自定义 ASP.NET Core 中间件

在 Asp.net Core MVC 中定义自定义客户端验证规则

带有 Windows 身份验证的 ASP.NET Core 2.1 自定义 RoleProvider