.NET Core中灵活使用反射

前言

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

什么是反射?

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

反射的作用

  1. 动态加载程序集。

  2. 获取类型信息。

  3. 创建对象和调用方法。

  4. 访问和操作成员。

  5. 扩展框架和库。

注意:由于反射是一种非常灵活和强大的机制,但也带来了一定的性能开销。因此,在使用反射时应慎重考虑其适用性,并权衡性能和灵活性的取舍。

自定义一个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();
    }

输出如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/284150.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

D47|动态规划-子序列part2

392.判断子序列&#xff1a; 初始思路&#xff1a; 左为判断公共子序列&#xff0c;右为判断子序列&#xff0c;感觉代码完全可以套用&#xff0c;如果公共子序列的长度是较短的字符串的长度的话即输出true&#xff0c;如果不是即输出false。 class Solution {public boolean…

【openlayers-5】地图点、线、面等要素添加

1、添加点 //创建一个点 var point new ol.Feature({geometry: new ol.geom.Point([117.2, 35.8] ),}) //设置点的样式信息 point.setStyle(new ol.style.Style({//填充色fill: new ol.style.Fill({color: rgba(255, 255, 255, 0.2),}),//边线颜色stroke: new ol.style.Strok…

Unity坦克大战开发全流程——游戏场景——游戏界面——设置界面复用

游戏场景——游戏界面——设置界面复用 先将开始场景当中的设置面板复制过来 由于设置面板挂载的脚本都是相同的&#xff0c;在BeginScene中关闭设置面板时不会报空&#xff0c;而在GameScene中关闭设置面板时却会报空&#xff0c;这是因为监听事件中的单例模式调用的实例是Beg…

68内网安全-域横向PTHPTKPTT哈希票据传递

今天讲PTH&PTK&PTT&#xff0c; PTH(pass the hash) #利用 lm 或 ntlm 的值进行的渗透测试 PTT(pass the ticket) #利用的票据凭证 TGT 进行的渗透测试 用的Kerberos 协议 PTK(pass the key) #利用的 ekeys aes256 进行的渗透测试 lm加密算法是2003以前的老版&…

动画墙纸:将视频、网页、游戏、模拟器变成windows墙纸——Lively Wallpaper

文章目录 前言下载github地址&#xff1a;网盘 关于VideoWebpagesYoutube和流媒体ShadersGIFs游戏和应用程序& more:Performance:多监视器支持&#xff1a;完结 前言 Lively Wallpaper是一款开源的视频壁纸桌面软件&#xff0c;类似 Wallpaper Engine&#xff0c;兼容 Wal…

按照故障码类型分类的API接口

随着汽车的普及&#xff0c;车辆故障也成为了一个不可忽视的问题。对于车主来说&#xff0c;及时了解故障码的含义以及解决方案十分重要。挖数据平台为解决这一问题&#xff0c;提供了一套按照故障码类型分类的API接口&#xff0c;用于查询车辆故障、故障码适用品牌以及提供相应…

当 Redis 遇上 Serverless

亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术&#xff0c;观点&#xff0c;和项目&#xff0c;并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏…

杂文月刊投稿方式论文发表要求

《杂文月刊》是由国家新闻出版总署批准的正规文学类期刊。主要内容取向&#xff1a;杂文、散文、小说、诗歌、漫画、文学评论、艺术评论、戏剧文化、地方文化、非遗文化、美学艺术、教育等历史、文化、文学、艺术类的文章。是广大专家、学者、教师、学子发表论文、交流信息的重…

docker 在线安装mysql 8.0.21版本

1、拉取mysql 8.0.21版本镜像 2、查看镜像 docker images 3、在宿主机 /usr/local/mysql 下的 conf 文件夹下&#xff0c;创建 my.cnf 文件&#xff0c;并编辑内容 [mysql] default-character-setutf8 [client] port3306 default-character-setutf8 [mysqld] port3306 se…

Win10取消开机密码

1、首先确认你的 Windows 系统帐户中添加了密码。您可以在设置 - 帐户 - 登录选项中查看电脑是否有添加本机密码。 2、按 WinR 打开运行窗口&#xff0c;在窗口中输入 netplwiz 并按确定。 3、在弹出的用户帐户控制中&#xff0c;我们可以看到当前已添加密码的帐户。把要使用本…

可拖拽流程图组件开发

效果 说在前面 流程图在技术领域是一种常见的可视化工具&#xff0c;用于展示系统、应用或业务流程的各个步骤以及它们之间的关系。它们可以帮助开发人员和项目团队更好地理解和规划复杂的流程&#xff0c;从而提高工作效率和准确性。但是&#xff0c;传统的静态流程图有时无法…

【Vulnhub 靶场】【Looz: 1】【简单】【20210802】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/looz-1,732/ 靶场下载&#xff1a;https://download.vulnhub.com/looz/Looz.zip 靶场难度&#xff1a;简单 发布日期&#xff1a;2021年08月02日 文件大小&#xff1a;2.1 GB 靶场作者&#xff1a;mhz_cyber &…

侯捷C++ 2.0 新特性

关键字 nullptr and std::nullptr_t auto 一致性初始化&#xff1a;Uniform Initialization 11之前&#xff0c;初始化方法包括&#xff1a;小括号、大括号、赋值号&#xff0c;这让人困惑。基于这个原因&#xff0c;给他来个统一&#xff0c;即&#xff0c;任何初始化都能够…

文献速递:人工智能医学影像分割---高效的MR引导CT网络训练,用于CT图像中前列腺分割

01 文献速递介绍 如今&#xff0c;根据国家癌症研究所的报告&#xff0c;美国约有9.9%的男性患有前列腺癌。1 此外&#xff0c;根据美国癌症协会的数据&#xff0c;预计2019年将有174,650个新病例被诊断出前列腺癌&#xff0c;与此同时大约有31,620名男性将死于前列腺癌。因此…

YOLOv8改进 | 检测头篇 | ASFF改进YOLOv8检测头(全网首发)

一、本文介绍 本文给大家带来的改进机制是利用ASFF改进YOLOv8的检测头形成新的检测头Detect_ASFF&#xff0c;其主要创新是引入了一种自适应的空间特征融合方式&#xff0c;有效地过滤掉冲突信息&#xff0c;从而增强了尺度不变性。经过我的实验验证&#xff0c;修改后的检测头…

计算机组成原理——中央处理器cpu21-40

18、某计算机的指令流水线由4个功能段组成&#xff0c;指令流经各功能段的时间&#xff08;忽略各功能段之间的缓存时间&#xff09;分别为90ns、80ns、70ns和60ns&#xff0c;则该计算机的CPU时钟周期至少是多少。A A、 90ns     B、 80ns C、 70ns     D、 60ns …

匿名短信发送网站搭建教程

​​​​​​​​​​​​​​详细教程链接 软件功能&#xff1a; 主要功能是可以去帮助一些用户发送匿名短信&#xff0c;不带你的真实号码&#xff0c;比如热恋中闹脾气的小情侣&#xff0c;短信的成本0.1&#xff0c;卖别人假设价格设置1元/条&#xff0c;利润就有80% 当…

Debezium日常分享系列之:Debezium 通知

Debezium日常分享系列之&#xff1a;Debezium 通知 一、概论二、Debezium通知格式三、Debezium 有关初始快照状态的通知四、Debezium 有关增量快照进度的通知五、启用 Debezium 通知六、访问 Debezium JMX 通知七、自定义通知渠道八、应用案例 一、概论 Debezium 通知提供了一…

MySql——1146 - Table‘mysql.proc‘doesn‘t exit是这个

项目场景&#xff1a; 做自己的小项目需要连接mysql数据库 问题描述 点击数据库时报错 1146 - Table’mysql.proc’doesn’t exit 原因分析&#xff1a; 误删原生的mysql数据库 解决方案&#xff1a; 重新安装装部署mysql就好了 注意不要轻易删除原生的东西

JMeter(十六)-JMeter断言

十六、JMeter断言 1.简介 断言组件用来对服务器的响应数据做验证&#xff0c;常用的断言是响应断言&#xff0c;其支持正则表达式。虽然我们的通过响应断言能够完成绝大多数的结果验证工作&#xff0c;但是JMeter还是为我们提供了适合多个场景的断言元件&#xff0c;辅助我们来…