反 射

二、反射

1.dll-IL-metadata 反射

|C#------->编译器编译----->DLL/EXE------->ClR/JIT–>机器码
|-------------------------------- ↙--------↘--------↗--------------------
|-----------------------------↙---------------↘↗-------------------------
|------------------------metadta--------------IL---------------------------
metadta:元数据,清单数据,声明的东西在里面,描述IL里面有啥
IL:中间语言,面向对象语言

2.反射加载dll,读取modle,类,方法,特性

      //普通类型
      IDBHelper dBHelper = new MySqlHelper();
      dBHelper.Query();
      
      //反射
      Assembly assembly = Assembly.Load("Ruan.DB.Mysql");//dll名称,从当前目录加载  1.加载DLL
      //Assembly.LoadFile();//完成路径 加载不会错,但是如果没有依赖项,使用的时候就会出错
      //Assembly assembly1 = Assembly.LoadFrom("Ruan.DB.Mysql.dll");//带后缀或者完整路径
      foreach (var item in assembly.GetTypes())
      {
          Console.WriteLine(item.FullName);
          //Type type = assembly.GetType("Ruan.DB.Mysql.MysqlHelper");//完整的类型名称
          Type type = assembly.GetType(item.FullName);  //2.获取类型信息
          object objHelper = Activator.CreateInstance(type);//3.创建对象
          IDBHelper idBHelper = (IDBHelper)objHelper;//4.类型转变
          idBHelper.Query();
      }    
      //带参数构造
      Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
      Type type = assembly.GetType("Ruan.DB.SqlServer.ReflectionTest");
      Object activator = Activator.CreateInstance(type);
      Object activator1 = Activator.CreateInstance(type,new Object[] {134});//与要调用构造函数的参数数量、顺序和类型匹配的参数数组
      Object activator2 = Activator.CreateInstance(type, new Object[] { "123" });

    public class SqlServerHelper : IDBHelper
    {
        public SqlServerHelper()
        {
           // Console.WriteLine("{0}被构造", this.GetType().Name);
        }
        public void Query()
        {
           // Console.WriteLine("{0}.Query", this.GetType().Name);
        }
    }

3.反射创建对象,反射+简单工厂+配置文件

配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
  <appSettings>
    <add key="IDBHelperConfig" value="Ruan.DB.Mysql.MySqlHelper"/>  //设置config,将字段保存到Config里面
  </appSettings>
</configuration>

反射+简单工厂

    //建立工厂
    public class Factory
    {
         //读Config   静态字段,一开始就已经初始化,在这里报错,进不去这个方法,就会抛出异常
         //private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
         // private static string DllName = IDBHelperConfig.; 
         // private static string TypeName = IDBHelperConfig; 
         //工厂创建对象
        public static IDBHelper GreateHelper() 
        {
            string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
            string DllName = IDBHelperConfig.Substring(0, IDBHelperConfig.LastIndexOf('.'));  
            string TypeName = IDBHelperConfig; 
            Assembly assembly = Assembly.Load(DllName);//1.加载DLL
            Type type = assembly.GetType(TypeName);  //2.获取类型信息
            object objHelper = Activator.CreateInstance(type);//3.创建对象
            IDBHelper idBHelper = (IDBHelper)objHelper;//4.类型转变
            return idBHelper;
        }
    }
//Reflection+factory+Config
//程序的可配置 可扩展
IDBHelper dBHelper = Factory.GreateHelper();
dBHelper.Query();

4.破坏单例

破坏单例

//Reflection
//单例只可以实例化一次,构造函数私有化,提供一个静态方法,通过静态方法获取实例,静态的实例
Singleton singleton = Singleton.GeInstance();
Singleton singleton1 = Singleton.GeInstance();
Singleton singleton2 = Singleton.GeInstance();//调用的都是一个

//反射可以破坏单例,其实也就是可以调用私有的构造函数
Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
Type type = assembly.GetType("Ruan.DB.SqlServer.Singleton");
Singleton singleton3 = (Singleton)Activator.CreateInstance(type,true);//这里多个true
Singleton singleton4 = (Singleton)Activator.CreateInstance(type,true);
Singleton singleton5 = (Singleton)Activator.CreateInstance(type,true);

创建单例

namespace Ruan.DB.SqlServer
{
    public sealed class Singleton
    {
        private static Singleton singleton = null;  //静态实例

        private Singleton()    //构造函数私有化后,外界没法构造
        {
            Console.WriteLine("Singleton被构造");
        }
        static Singleton()    //静态构造
        {
            singleton = new Singleton();
        }

        public static Singleton GeInstance() //通过静态方法,来调用实例
        {
            return singleton;
        }
    }
}

5.泛型反射

//泛型
Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
Type type = assembly.GetType("Ruan.DB.SqlServer.GenericClass`3"); //`3占位符表示几个
//object oGeneric = Activator.CreateInstance(type);//要指定
Type newType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });//指定type
object oGeneric = Activator.CreateInstance(newType);
    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);
        }
    }

6.反射调用实例方法,静态方法,重载方法 选修:调用私有方法,调用泛型方法

//Reflection+Method
//举例:MVC URL地址一类名称+方法名称
Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
Type type = assembly.GetType("Ruan.DB.SqlServer.ReflectionTest");
object oReflection = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("Show1");
methodInfo.Invoke(oReflection, null);
MethodInfo methodInfo1 = type.GetMethod("Show2");
methodInfo1.Invoke(oReflection, new object[] {123});
MethodInfo methodInfo2 = type.GetMethod("Show3", new Type[] { });//重载方法,重载的可以传递一个参数列表,Type[]{}类型的数组
methodInfo2.Invoke(oReflection, new object[] { });
MethodInfo methodInfo2_1 = type.GetMethod("Show3", new Type[] {typeof(int)});
methodInfo2_1.Invoke(oReflection, new object[] {123});
MethodInfo methodInfo3 = type.GetMethod("Show4",BindingFlags.Instance|BindingFlags.NonPublic);//调用私有的方法
methodInfo3.Invoke(oReflection, new object[] {"私有方法"});
MethodInfo methodInfo4 = type.GetMethod("Show5");
methodInfo4.Invoke(null,new object[] {"静态方法"});//静态方法不需要实例化,可以给个实例,也可以是null

调用泛型方法

//Reflection+Method+泛型
Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
Type type = assembly.GetType("Ruan.DB.SqlServer.GenericDouble`1"); 
Type newType = type.MakeGenericType(new Type[] { typeof(string)});
object oGeneric = Activator.CreateInstance(newType);
MethodInfo method = newType.GetMethod("show");
MethodInfo newMethod = method.MakeGenericMethod(new Type[] { typeof(string),typeof(int),typeof(DateTime)});
                    newMethod.Invoke(oGeneric, new object[] {"泛型方法",123,DateTime.Now});
```csharp
在这里插入代码片
 public class ReflectionTest
    {
        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());
        }

        public void Show1() 
        {
            Console.WriteLine("这里是{0}的Show1", this.GetType());
        }
        public void Show2(int id)
        {
            Console.WriteLine("这里是{0}的Show2", this.GetType());
        }
        public void Show3() 
        {
            Console.WriteLine("这里是{0}的Show3", this.GetType());
        }
        public void Show3(int id)
        {
            Console.WriteLine("这里是{0}的Show3_1", this.GetType());
        }
        public void Show3(string name)
        {
            Console.WriteLine("这里是{0}的Show3_2", this.GetType());
        }
        public void Show3(string name,int id)
        {
            Console.WriteLine("这里是{0}的Show3_3", this.GetType());
        }
        private void Show4(string name)
        {
            Console.WriteLine("这里是{0}的Show4", this.GetType());
        }
        public static void Show5(string name) 
        {
            Console.WriteLine("这里是{0}的Show4", typeof(ReflectionTest));
        }

    }
     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<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);
        }
    }

7.反射字段和属性,分别获取值和设置值

//Reflection+Property/Field
//ORM
//普通
People people = new People();
people.Id = 123;
people.Name = "LIN";
people.Description = "description";

Console.WriteLine($"{people.Id}");
Console.WriteLine($"{people.Name}");
Console.WriteLine($"{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, 111);
     else if (prop.Name.Equals("Name"))
        prop.SetValue(oPeople, "LIU");
     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, "de");
       Console.WriteLine($"{type.Name},{field.Name},{field.GetValue(oPeople)}");
}

例子:typeDTO复制typePeople

 //复制类 遍历属性 
People people1 = new People();  //DTO模型基本上一样,不一样的化要建立一个特性。
people1.Id = 123;
people1.Name = "LIN";
people1.Description = "description";

PeopleDTO peopleDTO = new PeopleDTO()
{
     Id = people1.Id,
     Name = people1.Name,
     Description=people1.Description,
};

Type typePeople = typeof(People);
Type typeDTO = typeof(PeopleDTO);
Object type = Activator.CreateInstance(typeDTO);

foreach (var prop in typeDTO.GetProperties())
{
       //if (prop.Name.Equals("Id"))
       //{
       //  //  Object value = typePeople.GetProperty("Id").GetValue(people1); 
       //    Object value = typePeople.GetProperty(prop.Name).GetValue(people1);
       //    prop.SetValue(peopleDTO, value);
       //}
       //else if (prop.Name.Equals("Name"))
       //{
       //   // Object value = typePeople.GetProperty("Name").GetValue(people1); 
       //    Object value = typePeople.GetProperty("prop.Name").GetValue(people1);
       //    prop.SetValue(peopleDTO, value);
       //}
       Object value = typePeople.GetProperty(prop.Name).GetValue(people1);
       prop.SetValue(type, value);//名字一样时
}
foreach (var field in typeDTO.GetFields()) 
{
       Object value = typePeople.GetField(field.Name).GetValue(people1);
       field.SetValue(type,value);
}

8.反射的好处和局限

反射:System.Reflection .Net框架提供的帮助类库,可以读取并且使用metadata
反射优点:动态
反射缺点:
1.复杂,
2.避开了编译器检查
MethodInfo methodInfo = type.GetMethod(“Ssss”);没有这个类
3.性能不好
CommonTime=24,ReflectionTime=4034
ReflectionOneTime=46//空间换时间,声明一次,多次使用基本不影响
MVC第一次访问很慢 后面快
EF第一次访问很慢 后面快

//性能对比
Monitor.Show();//CommonTime=44,ReflectionTime=4331
namespace MyReflection
{
    public class Monitor
    {
        public static void Show() 
        {
            long commonTime = 0;
            long reflectionTime = 0;
            long reflectionOneTime = 0;//声明一次多次使用
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                for (int i = 0; i < 1000000; i++) 
                {
                    IDBHelper dBHelper = new SqlServerHelper();
                    dBHelper.Query();
                }
                stopwatch.Stop();
                commonTime = stopwatch.ElapsedMilliseconds;
            }
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                for (int i = 0; i < 1000000; i++) 
                {
                    Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
                    Type type = assembly.GetType("Ruan.DB.SqlServer.SqlServerHelper");
                    Object objHelper= Activator.CreateInstance(type);
                    IDBHelper dBHelper = (IDBHelper)objHelper;
                    dBHelper.Query();
                }
                stopwatch.Stop();
                reflectionTime = stopwatch.ElapsedMilliseconds;
            }
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                Assembly assembly = Assembly.Load("Ruan.DB.SqlServer");
                Type type = assembly.GetType("Ruan.DB.SqlServer.SqlServerHelper");
                for (int i = 0; i < 1000000; i++)
                {
                    Object objHelper = Activator.CreateInstance(type);
                    IDBHelper dBHelper = (IDBHelper)objHelper;
                    dBHelper.Query();
                }
                stopwatch.Stop();
                reflectionOneTime = stopwatch.ElapsedMilliseconds;
            }
            Console.WriteLine($"CommonTime={commonTime},ReflectionTime={reflectionTime},ReflectionTime={reflectionOneTime}");
        }
       
    }
}

转到目录↩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值