反射
二、反射
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}");
}
}
}