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);//获取类typeif (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);//春天}