C# 的反射机制

C# 的反射机制

反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌,还可以直接创建对象,即使这个对象的类型在编译时还不知道。

  1. 反射的用途:
1)使用`Assembly`定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。 
(2)使用`Module`了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。 
(3)使用`ConstructorInfo`了解构造函数的名称、参数、访问修饰符(如`pulic` 或`private`)和实现详细信息(如`abstract`或`virtual`)等。 
(4)使用`MethodInfo`了解方法的名称、返回类型、参数、访问修饰符(如`pulic` 或`private`)和实现详细信息(如`abstract`或`virtual`)等。
(5)使用`FiedInfo`了解字段的名称、访问修饰符(如`public`或`private`)和实现详细信息(如`static`)等,并获取或设置字段值。
(6)使用`EventInfo`了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。 
(7)使用`PropertyInfo`了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。 
(8)使用`ParameterInfo`了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
  1. 反射用到的命名空间:
1)`System.Reflection`
(2)`System.Type`
(3)`System.Reflection.Assembly`
  1. 反射用到的主要类:
1)`System.Type` 类--通过这个类可以访问任何给定数据类型的信息。
(2)`System.Reflection.Assembly`类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。
  1. System.Type类:

System.Type 类对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。

// 获取给定类型的Type引用有3种常用方式:
// 使用 C# typeof 运算符。
Type t = typeof(string);
// 使用对象GetType()方法。
string s = "grayworm";
Type t = s.GetType(); 
// 还可以调用Type类的静态方法GetType()。
Type t = Type.GetType("System.String");
  1. 获取给定类型的Type引用有3种常用方式:
// 使用 C# typeof 运算符。
Type t = typeof(string);
// 使用对象GetType()方法。
string s = "grayworm";
Type t = s.GetType(); 
// 还可以调用Type类的静态方法GetType()。
Type t = Type.GetType("System.String");

上面这三类代码都是获取string类型的Type,在取出string类型的Type引用t后,我们就可以通过t来探测string类型的结构了。

string n = "grayworm";
Type t = n.GetType();
foreach(MemberInfo mi in t.GetMembers())
{
    Console.WriteLine("{0}/t{1}",mi.MemberType,mi.Name);
}
  1. Type类的属性:
Name 数据类型名
FullName 数据类型的完全限定名(包括命名空间名)
Namespace 定义数据类型的命名空间名
IsAbstract 指示该类型是否是抽象类型
IsArray  指示该类型是否是数组
IsClass  指示该类型是否是类
IsEnum  指示该类型是否是枚举
IsInterface  指示该类型是否是接口
IsPublic 指示该类型是否是公有的
IsSealed 指示该类型是否是密封类
IsValueType 指示该类型是否是值类型
  1. Type类的方法:
GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息;
GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息;
GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息;
GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息;
GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息;
GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息;
GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo, PropertyInfo和其他类的Invoke()方法;

查看类中的构造方法:

NewClass nc = new NewClass();
Type t = nc.GetType();
ConstructorInfo[] ci = t.GetConstructors(); // 获取类的所有构造函数
foreach(ConstructorInfo c in ci)  // 遍历每一个构造函数
{
    ParameterInfo[] ps = c.GetParameters(); // 取出每个构造函数的所有参数
    foreach(ParameterInfo pi in ps) // 遍历并打印该构造函数的所有参数
    {
        Console.WriteLine(pi.ParameterType.TOString() + " " + pi.Name + ",");
    }
    Console.WriteLine();
}

用构造函数动态生成对象:

Type t = typeof(NewClass);
Type[] pt = new Type[2];
pt[0] = typeof(string);
pt[1] = typeof(string);
// 根据参数类型获取构造函数
ConstructorInfo ci = t.GetConstructor(pt);
// 构造Object数组, 作为构造函数的输入参数
object[] obj = new object[2]{"wiki", "dualseason.com"};
object o = ci.Invoke(obj);
// 调用生成的对象的方法测试是否对象成功生成
((NewClass)o).show();

用Activator生成对象:

Type t = typeof(NewClass);
// 构造函数的参数
object[] obj = new object[2] {"wiki", "dualseason.com"};
// 用Activator的CreateInstanc静态方法, 生成新对象
object o = Activator.CreateInstance(t, "wiki", "dualseason.com");
// ((NewClass)o).show();

查看类中的属性

NewClass nc = new NewClass();
Type t = nc.GetType();
PropertyInfo[] pis = t.GetProperties();
foreach(PropertyInfo pi in pis)
{
    Console.WriteLine(pi.Name);
}

查看类中的public方法

NewClass nc = new NewClass();
Type t = nc.GetType();
MethodInfo[] mis = t.GetMethods();
foreach(MethodInfo mi in mis)
{
    Console.WriteLine(mi.ReturnType + " " + mi.Name);
}

查看类中的public字段

NewClass nc = new NewClass();
Type t = nc.GetType();
FieldInfo[] fis = t.GetFields();
foreach(FieldInfo fi in fis)
{
    Console.WriteLine(fi.Name);
}

用反射生成对象,并调用属性、方法和字段进行操作

NewClass nc = new NewClass();
Type t = nc.GetType();
Object obj = Activator.CreateInstance(t);
// 取得ID字段
FieldInfo fi = t.GetField("ID");
// 给ID字段赋值
fi.SetValue(obj, "k001");
// 取得MyName属性
PropertyInfo pi1 = t.GetProperty("MyName");
// 给MyName属性赋值
pi1.SetValue(obj, "grayworm", null);
PropertyInfo pi2 = t.GetProperty("MyInfo");
pi2.SetValue(obj, "dualseason.com", null);
// 取得show方法
MethodInfo mi = t.GetMethod("show");
// 调用show方法
mi.Invoke(obj, null);
  1. System.Reflection.Assembly类

    Assembly类可以获得程序集的信息,也可以动态加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。

    使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。

// 通过程序集名称返回Assembly对象
Assemb ass = Assembly.Load("ClassLibary831"); //dll名称无后缀
// 通过DLL文件名称返回Assembly对象
Assembly ass = Assembly.LoadFrom("ClassLibary831.dll");// 带后缀或者完整路径
// 通过Assembly获取程序集的类, 参数必须是类的全名
Type t = ass.GetType("ClassLibary831.NewClass");
// 通过Assembly获取程序集所有类
Type[] t = ass.GetTypes();
// 通过程序集名称反射
Assembly ass = Assembly.Load("ClassLibary831");
Type t = ass.GetType("ClassLibary831.NewClass");
object o = Activator.CreateInstance(t, "wiki", "http://dualseason.com");
MethodInfo mi = t.GetMethod("show");
mi.Invoke(o, null);
// 通过DLL文件全名反射所有类型
Assembly ass = Assembly.LoadFrom("LeadDream.dll");
Type[] ts = ass.GetTypes();
foreach(Type t in ts)
{
    if(t.FullName == "LeadDream.PropertyManagement.Handler")
    {
        object o = Activator.CreateInstance(t);
    }
}
  1. 应用实例
// dll名称无后缀, 从当前目录加载
Assembly assembly = Assembly.Load("LeadDream.DB.MySql");
// 完整路径的加载甚至可以是别的目录,加载不会错,但是如果没有依赖项,使用的时候会错
Assembly assembly = Assembly.LoadFile(@"D:\dualseason\LeadDream.DB.MySql.dll");
// 带后缀或者完整路径
Assembly assembly2 = Assembly.LoadFrom("LeadDream.DB.MySql.dll");
foreach (var item in assembly.GetModules())
{
    Console.WriteLine(item.FullyQualifiedName);
}
foreach (var item in assembly.GetTypes())
{
    Console.WriteLine(item.FullName);
}
// 获取类型信息
Type type = assembly.GetType("LeadDream.DB.MySql.MySqlHelper");
// 创建对象,oDBHelper是objec不能调用oDBHelper.Query(),但实际上方法是有的只是编译器不认可,需要类型转换
object oDBHelper = Activator.CreateInstance(type);
// 类型转换
IDBHelper iDBHelper = (IDBHelper)oDBHelper;
// 方法调用
iDBHelper.Query();
// appSetting.conf
"IDBHelper": {
    "DLLName": "LeadDream.DB.MySql",
    "TypeName": "LeadDream.DB.MySql.MySqlHelper"
},

public class Factory
{
    private IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    private static string DllName = ConfiguationManager.AppSettings["IDBHelper:DLLName"];
    private static string TypeName = ConfiguationManager.AppSettings["IDBHelper:TypeName"];
    public static IDBHelper CreateHelper() 
    {
        Assembly assembly = Assembly.Load(DllName);
        Type type = assembly.GetType(TypeName);
        object oDBHelper = Activator.CreateInstance(type);
        IDBHelper iDBHelper = (IDBHelper)oDBHelper;
        return iDBHelper;
    }
}

// IOC原理:反射 + 配置文件 + 工厂
public void Main(string[] args)
{
    IDBHelper iDBHelper = Factory.CreateHelper();
    iDBHelper.Query();
}
// 测量反射的额外所需时间
namespace MyReflection
{
    public class Monitor
    {
        public static void Show()
        {
            long commonTime = 0;
            long reflectionTime = 0;
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                for(int i = 0; i < 100000; i++)
                {
                    IDBHelper iDBHelper = new SqlServerHelper();
                    iDBHelper.Query();
                }
                watch.Stop();
                commonTime = watch.ElapsedMilliseconds;
            }
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Assembly assembly = Assembly.Load("LeadDream.DB.SqlServer");
                Type dbHelperType = assembly.GetType("LeadDream.DB.SqlServer.SqlServerHelper");
                for(int i = 0; i< 100000; i++)
                {
                    object oDBHelper = Activator.CreateInstance(dbHelperType);
                    IDBHelper dbHelper = (IDBHelper)oDBHelper;
                    dbHelper.Query();
                }
                watch.Stop();
                reflectionTime = watch.ElapsedMilliseconds;
            }
            Console.WriteLine("commonTime={0} reflectionTime={1}", commonTime, reflectionTime);
        }
    }
}
// 补充单例模式代码
namespace LeadDream.DB.SqlServer
{
    public sealed class Singleton
    {
        private static Singleton _Singleton = null;
        private Singleton()
        {
            Console.WriteLine("Singleton被构建");
        }
        
        static Singleton()
        {
            _Singleton = new Singleton();
        }
        
        public static Singleton GetInstance()
        {
            return _Singleton;
        }
    }
}
// Reflection + Instance
SingleTon singleton = new Singleton();
Singleton singleton1 = Singleton.GetInstance();
Singleton singleton2 = Singleton.GetInstance();
Singleton singleton3 = Singleton.GetInstance();

{
    Assembly assembly = Assembly.Load("LeadDream.DB.SqlServer");
    Type type = assembly.GetType("LeadDream.DB.SqlServer.Singleton");
    Singleton singleton4 = (Singleton)Activator.CreateInstance(type, true);
    Singleton singleton5 = (Singleton)Activator.CreateInstance(type, true);
    Singleton singleton6 = (Singleton)Activator.CreateInstance(type, true);
}
{
    Assembly assembly = Assembly.Load("LeadDream.DB.SqlServer");
    Type type = assembly.GetType("LeadDream.DB.SqlServer.ReflectionTest");
    object oReflectionTest1 = Activator.CreateInstance(type);
    object oReflectionTest2 = Activator.CreateInstance(type, new object[] { 123 });
    object oReflectionTest3 = Activator.CreateInstance(type, new object[] { "123" });
}
{
    Assembly assembly = Assembly.Load("LeadDream.DB.SqlServer");
    Type type = assembly.GetType("LeadDream.DB.SqlServer.ReflectionTest");
    object oGeneric = Activator.CreateInstance(type);
    Type newType = Type.MakeGenericType(new Type { typeof(int), typeof(string), typeof(DateTime) });
    object oGeneric = Activator.CreateInstance(newType);
}
// LeadDream.DB.SqlServer
namespace LeadDream.DB.SqlServer
{
    public class ReflectionTest
    {
        #region Identity
        public ReflectionTest()
        {
            Console.WriteLine("这里是{0}无参数构造函数", this.GetType());
        }
        public ReflectionTest(string name)
        {
            Console.WriteLine("这里是{0} 有参数构造函数", this.GetType());
        }

        public ReflectionTest(int id)
        {
            Console.WriteLine("这里是{0} 有参数构造函数", this.GetType());
        }
        #endregion

        #region Method
        public void Show1()
        {
            Console.WriteLine("这里是{0}的Show1", this.GetType());
        }
        public void Show2(int id)
        {

            Console.WriteLine("这里是{0}的Show2", this.GetType());
        }
        public void Show3(int id, string name)
        {
            Console.WriteLine("这里是{0}的Show3", this.GetType());
        }
        public void Show3(string name, int id)
        {
            Console.WriteLine("这里是{0}的Show3_2", this.GetType());
        }
        public void Show3(int id)
        {

            Console.WriteLine("这里是{0}的Show3_3", this.GetType());
        }
        public void Show3(string name)
        {

            Console.WriteLine("这里是{0}的Show3_4", this.GetType());
        }
        public void Show3()
        {

            Console.WriteLine("这里是{0}的Show3_1", this.GetType());
        }
        private void Show4(string name)
        {
            Console.WriteLine("这里是{0}的Show4", this.GetType());
        }
        public static void Show5(string name)
        {
            Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest));
        }
        #endregion
    }
}
// MVC URL地址--类名称 + 方法名称
Assembly assembly = Assembly.Load("LeadDream.DB.SqlServer");
Type type = assembly.GetType("LeadDream.DB.SqlServer.ReflectionTest");
object oReflectionTest = Activator.CreateInstance(type);
foreach(var item in type.GetMethods())
{
    Console.WriteLine(item.Name);
}
// oReflectionTest.Show1();
{
    MethodInfo method = type.GetMethod("Show1");
    method.Invoke(oReflectionTest, null);
}
{
    MethodInfo method = type.GetMethod("Show2");
    method.Invoke(oReflectionTest, new object[] { 123 });
}
{
    MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });
    method.Invoke(oReflectionTest, new object[] { 123 });
}
{
    MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });
    method.Invoke(oReflectionTest, new object[] { "Ant" });
}
{
    MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
    method.Invoke(oReflectionTest, new object[] { 234, "W" });
}
{
    MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
    method.Invoke(oReflectionTest, new object[] { "W", 234 });
}
{
    MethodInfo method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
    method.Invoke(oReflectionTest, new object[] { "天空之上" });
}
{
    Type typeGenericDouble = assembly.GetType("LeadDream.DB.SqlServer.GenericDouble");
    Type newType = typeGenericDouble.MakeGenericType(new Type[] { typeof(int) });
    object oGeneric = Activator.CreateInstance(newType);
    MethodInfo method = newType.GetMethod("Show");
    MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
    methodNew.Invoke(oGeneric, new object[] { 123, "流浪诗人", DateTime.Now });
}
namespace LeadDream.DB.SqlServer
{
    public class GenericClass<T, W, X>
    {
        public void Show(T t, W w, X x)
        {
            Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name);
        }
    }

    public class GenericMethod
    {
        public void Show<T, W, X>(T t, W w, X x)
        {
            Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name);
        }
    }

    public class GenericDouble<T>
    {
        public void Show<W, X>(T t, W w, X x)
        {
            Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name);
        }
    }
}
// ORM => Reflection + Property/Field
People people = new People();
people.Id = 123;
people.Name = "ReactSpring";
people.Description = "岭梦科技CEO";
//    Console.WriteLine($"people.Id={people.Id}");
//    Console.WriteLine($"people.Name={people.Name}");
//    Console.WriteLine($"people.Description={people.Description}");
Type type = typeof(People);
object oPeople = Activator.CreateInstance(type);
//    foreach (var prop in type.GetProperties())
//    {
//        Console.WriteLine(type.Name);
//        Console.WriteLine(prop.Name);
//        Console.WriteLine(prop.GetValue(oPeople));
//        if (prop.Name.Equals("Id"))
//        {
//            prop.SetValue(oPeople, 234);
//        }
//        else if (prop.Name.Equals("Name"))
//        {
//            prop.SetValue(oPeople, "风潇潇");
//        }
//        Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}");
//    }
foreach (var field in type.GetFields())
{
    Console.WriteLine(type.Name);
    Console.WriteLine(field.Name);
    Console.WriteLine(field.GetValue(oPeople));
    if (field.Name.Equals("Description"))
    {
        field.SetValue(oPeople, "首席技术执行官");
    }
    Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oPeople)}");
}

{
    People people = new People();
    people.Id = 123;
    prople.Name = "小春";
    people.Description = "CEO";
    
    //    {   //硬编码
    //        //PeopleDTO peopleDTO = (PeopleDTO)people;
    //        PeopleDTO peopleDTO = new PeopleDTO()
    //        {
    //            Id = people.Id,
    //            Name = people.Name,
    //            Description = people.Description
    //        };
    //    }
    {
        Type typePeople = typeof(People);
        Type typePeopleDTO = typeof(PeopleDTO);
        object peopleDTO = Activator.CreateInstance(typePeopleDTO);
        foreach(var prop in typePeopleDTO.GetProperties())
        {
            object value = typePeople.GetProperty(prop.Name).GetValue(prople);
            prop.SetValue(peopleDTO, value);
        }
        foreach(var field in typePeopleDTO.GetFields())
        {
            object value = typePeople.GetField(field.Name).GetValue(people);
            field.SetValue(peopleDTO, value);
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReactSpring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值