当前位置: 首页 > article >正文

C#进阶1

C#进阶1

本文章主要介绍C#的进阶知识,如反射,特性....
参考视频链接

原码

文章目录

  • C#进阶1
  • 反射
    • 步骤
    • 泛型反射
      • 调用方法
    • 获取属性
  • 特性
    • 特性的定义
    • 步骤
      • 扩展枚举练习


反射

在 C# 中,反射(Reflection)是一种强大的机制,允许程序在运行时检查和操作类型、方法、属性等元数据。通过反射,你可以在运行时动态地创建对象、调用方法、访问属性,甚至修改类型的行为。反射在许多场景中非常有用

  • 反射思路:首先获取程序中的类,然后通过类再获取方法,参数,构造方法等
  • 在项目路径下的debug文件中,.dll是首先要获取的,因为他是程序一次编译形成的产物,相关信息都可以通过反射获取
    在这里插入图片描述

步骤

  • 加载dll dll是经过一次编译形成的文件

    Assembly assembly = Assembly.Load("2024_10_30_Project");
    
  • 获取类

    Type type = assembly.GetType("_2024_10_30_Project.Person");
    
  • 调用构造,创建实例

     //创建无参
            Person p = (Person)Activator.CreateInstance(type, true);
            p.say();
    
            //调用有参
            Object o = Activator.CreateInstance(type, new Object[] { "我要说话" });
    

泛型反射

  • 对于类的话,如果类中有泛型,那么在获取类的时候要制定泛型个数,然后说明泛型

      //调用泛型无参  `3表示三个泛型
            Type type2 = assembly.GetType("_2024_10_30_Project.Zhou`3");
            //说明泛型类型
            type2 = type2.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
            //创建
            Object o2 = Activator.CreateInstance(type2);
    

调用方法

  • 类中获取方法,所以得有类,先获取实例,然后进行方法的获取;方法获取要制定获取的方法名,如果不是泛型方法,在获取方法名的同时,指定方法参数类型,如果是泛型方法,就先获取方法名,然后再制定泛型参数,最后调用方法。

     //方法反射
            {
                MethodInfo method3 = type2.GetMethod("zMethod3", new Type[] { });
                method3.Invoke(o2, null);
            }
            {
                var method2 = type2.GetMethod("zMethod2", new Type[] { typeof(string), typeof(int) });
                method2.Invoke(o2, new object[] { "张三", 11 });
            }
            {
                //调用私有
                MethodInfo method1 = type2.GetMethod("zMethod1", BindingFlags.Instance | BindingFlags.NonPublic);
                method1.Invoke(o2, new object[] { "我是私有m1" });
            }
            {
                //调用泛型共有方法
                Assembly a1 = Assembly.Load("2024_10_30_Project");
                Type type1 = a1.GetType("_2024_10_30_Project.TestClaz`1");
                type1 = type1.MakeGenericType(new Type[] { typeof(int) });
                Object oo1 = Activator.CreateInstance(type1);
                MethodInfo me1 = type1.GetMethod("m1");
                var me2 =me1.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
                me2.Invoke(oo1, new object[] { 1, "张张", DateTime.Now });
            }
            {
                //调用泛型私有方法
                Assembly a1 = Assembly.Load("2024_10_30_Project");
                Type type1 = a1.GetType("_2024_10_30_Project.TestClaz`1");
                type1 = type1.MakeGenericType(new Type[] { typeof(int) });
                Object oo1 = Activator.CreateInstance(type1);
                MethodInfo me1 = type1.GetMethod("m2",BindingFlags.Instance|BindingFlags.NonPublic);
                var me2 = me1.MakeGenericMethod(new Type[] { typeof(string) });
                me2.Invoke(oo1, new object[] { 1, "私有" });
            }
    

获取属性

由于获取的方式都参不多,大家可自信查阅api

{
                Assembly a1 = Assembly.Load("2024_10_30_Project");
                Type type1 = a1.GetType("_2024_10_30_Project.TestClaz`1");
                type1 = type1.MakeGenericType(new Type[] { typeof(int) });
                Object oo1 = Activator.CreateInstance(type1);
                var pr = type1.GetProperties();
                foreach(var pro in pr)
                {
                    Console.WriteLine(pro.Name);
                    if (pro.Name.Equals("age"))
                    {
                        pro.SetValue(oo1, 11);//设置属性值
                    }
                    Console.WriteLine(pro.GetValue(oo1));
                }

            }

特性

特性类似于java中的注解,用于给元素添加额外的信息

特性的定义

  • 如需要自定义特性,需要继承Attribute,使用如果自定义特性包含Attribute,可省略

     class CustomerAttribute:Attribute
    {
    }
    
    [Customer]
    class Person
    {
        public static void say()
        {
            Console.WriteLine("我是特性说话了");
        }
    }
    

步骤

  • 声明自定义特性,定义属性和方法

    namespace AttriProject
    {
        class CustomerAttribute:Attribute
        {
            public string name { get; set; }
            public int age { get; set; }
    
            public void say()
            {
                Console.WriteLine("我是特性类");
            }
        }
    }
    
  • 然后在Person类上添加特性

      //初始化特性,给特性赋值
        [Customer(name ="张三",age =11)]
        class Person
        {
            [Customer]
            public string name { get; set; }
            public static void say()
            {
                Console.WriteLine("我是特性说话了");
            }
        }
    
  • 在Manager类声明方法,通过反射获取Person类的特性

      public static void show()
            {
                Type type = typeof(Person);//获取类type
                if (type.IsDefined(typeof(CustomerAttribute), true)) //看类中是否包含特性
                {
                    //获取类的特性实例
                    CustomerAttribute customer = (CustomerAttribute)type.GetCustomAttribute(typeof(CustomerAttribute));
                    Console.WriteLine($"{customer.age}-{customer.name}");
                    customer.say();
                }
                PropertyInfo proin = type.GetProperty("name");
                if (proin.IsDefined(typeof(CustomerAttribute), true)) //看类中是否包含特性
                {
                    //获取类的特性实例
                    CustomerAttribute customer = (CustomerAttribute)proin.GetCustomAttribute(typeof(CustomerAttribute));
                    customer.say();
                }
            }
    

扩展枚举练习

  • 定义自定义特性

     class CustomerAttribute:Attribute
        {
            private string _remark;
            public string Remark { get => _remark; set => _remark = value; }
    
            public CustomerAttribute(string remark)
            {
                this._remark = remark;
    
            }
    }
    
  • 定义枚举,并在字段上标注特性

   enum CEnum
    {
        [CustomerAttribute("春天")]
        SPRING=1,
        [CustomerAttribute("夏天")]
        SUMMER =2,
        [CustomerAttribute("秋天")]
        AUTUMN =3,
        [CustomerAttribute("冬天")]
        WINTER =4
    }
  • 定义枚举扩展方法扩展方法为静态类中包含静态方法,静态方法参数用this标识,这样方法参数类型调用此方法,会自动进入该方法 扩展方法返回特性的属性值

        public static class RemarkExten
        {
            public static string GetRemark(this Enum en)
            {
                var type = en.GetType();
                var field = type.GetField(en.ToString());
                if (field.IsDefined(typeof(CustomerAttribute), true))
                {
                    var cu = (CustomerAttribute)field.GetCustomAttribute(typeof(CustomerAttribute));
                    return cu.Remark;
                }
                return "";
            }
        }
    
  • 主方法调用

     static void Main(string[] args)
            {
                Manager.show();
    
                CEnum c = CEnum.SPRING;
                var x = c.GetRemark();
                Console.WriteLine(x);//春天
                
            }
    

http://www.kler.cn/a/373974.html

相关文章:

  • 串口通信以及USART和UART以及IIC和SPI-学习笔记
  • 渗透测试-百日筑基—SQL注入篇时间注入绕过HTTP数据编码绕过—下
  • 达梦数据迁移工具DTS使用实践
  • Windows 上更新OpenSSL 到 1.1.1
  • Linux 安装nacos
  • Linux_04 Linux常用命令——tar
  • vue3 ref和reactive踩坑
  • 实现Vue3/Nuxt3 预览excel文件
  • git revert‌和git reset,慎用git revert‌
  • 高阶数据结构--图(graph)
  • 微服务架构设计的初次尝试——基于以太坊智能合约 + NestJS 微服务的游戏社区与任务市场系统:架构设计
  • Android 刘海屏适配指南
  • Python酷库之旅-第三方库Pandas(182)
  • Mybatis-plus解决兼容oracle批量插入
  • centos7之LVS-NAT模式传统部署和docker部署
  • golang中的测试用例
  • 数据分析——大量数据进行分析
  • Spring Boot 3 + Spring Security + Knife4j 无法访问 Swagger 文档的问题及解决方案
  • 如何抓住鸿蒙生态崛起的机遇,解决开发挑战,创造更好的应用体验
  • Linux笔记--基础入门
  • aws 部署测试环境服务+ip域名绑定
  • 全国计算机等级考试二级
  • 【Fargo】17:vs工程转qt构建:QT6 不支持32bit转向qt5.15.2
  • MYSQL--完整性约束
  • AR基础知识:SLAM同时定位和构图
  • 计算机网络:网络层 —— 开放最短路径优先 OSPF