本章学习内容
- dll-IL-metadata-反射
- 反射加载dll,读取module、类、方法、特性
- 反射创建对象,反射+简单工厂+配置文件
- 破坏单例 创建泛型
反射基础
反射是无处不在的,MVC-Asp.Net-ORM-IOC-AOP 几乎所有的框架都离不开反射
- 反编译工具不是用的反射,是一个逆向工程
- IL:也是一种面向对象语言,但是不太好阅读
- metadata元数据:数据清单,描述了DLL/exe里面的各种信息
- 反射Reflection:System.Reflection,是 .net Framework提供的一个帮助类库,可以读取并使用metadata
反射工具类
//加载dll
Assembly assembly1 = Assembly.Load("Ruanmou.DB.Mysql");//完整dll名称不需要后缀,从exe所在目录超找
Assembly assembly2 = Assembly.LoadFile(@"D:\xxx\xx\xx\Ruanmou.DB.Mysql.dll");//绝对路径
Assembly assembly3 = Assembly.LoadFrom("Ruanmout.DB.Mysql.dll");//当前路径
Assembly assembly4 = Assembly.LoadFrom(@"D:\xxx\xx\xx\Ruanmou.DB.Mysql.dll");//绝对路径
反射基本使用
j简单获取全部dll中的信息
foreach (var type in assembly1.GetTypes())
{
Console.WriteLine(type.Name);
foreach (var method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
foreach (var field in type.GetFields())
{
Console.WriteLine(field.Name);
}
}
调用类型中的不同参数的构造函数
foreach (ConstructorInfo ctor in type.GetConstructors())
{
Console.WriteLine(ctor.Name);
foreach (var paramter in ctor.GetParameters())
{
Console.WriteLine(paramter.ParameterType);
}
}
//不同的构造函数创建实例
object oTest1 = Activator.CreateInstance(type);//无参构造函数
object oTest2 = Activator.CreateInstance(type, new Object[] { 123 });//一个参数,参数类型类型为int的构造函数
object oTest3 = Activator.CreateInstance(type, new Object[] { "陌商" });//一个参数,参数为字符串的构造函数
反射最简单好处示例
//统一工厂
public class SimpleFactory
{
private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
private static string DllName = IDBHelperConfig.Split(',')[1];
private static string TypeName = IDBHelperConfig.Split(',')[0];
public static IDBHelper CreateInstance()
{
Assembly assembly = Assembly.Load(DllName);
Type type = assembly.GetType(TypeName);
object oDBHelper = Activator.CreateInstance(type);
IDBHelper iDBHelper = oDBHelper as IDBHelper;
return iDBHelper;
}
}
/// <summary>
/// 数据访问类抽象
/// </summary>
public interface IDBHelper
{
void Query();
}
Console.WriteLine("*****************Reflection+Factory+Config********************");
IDBHelper iDBHelper = SimpleFactory.CreateInstance();
iDBHelper.Query();
- 程序的可配置,通过修改配置文件就可以自动切换
- 实现类必须是事先已有的,而且在目录下面
- 没有写死类型,而是通过配置文件执行,反射创建的
- 可扩展:完全不修改原有代码,只是增加新的实现,copy,修改配置文件,就可以支持新功能
- 反射的动态加载和动态创建对象 以及配置文件结合
反射破坏单例模式
单例模式:类,能保证在整个进程中只有一个实例
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;
}
}
}
Singleton singleton1 = Singleton.GetInstance(); //new Singleton();
Singleton singleton2 = Singleton.GetInstance();
Singleton singleton3 = Singleton.GetInstance();
Singleton singleton4 = Singleton.GetInstance();
Singleton singleton5 = Singleton.GetInstance();
Console.WriteLine($"{object.ReferenceEquals(singleton1, singleton5)}");
单例模式,都是同一个静态变量_Singleton,以上所有sigleton实例都是同一个。
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.Singleton");
Singleton singletonA = (Singleton)Activator.CreateInstance(type, true);
Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);
Singleton singletonC = (Singleton)Activator.CreateInstance(type, true);
Singleton singletonD = (Singleton)Activator.CreateInstance(type, true);
Console.WriteLine($"{object.ReferenceEquals(singletonA, singletonD)}");
反射破坏了单例—就是通过反射调用了私有构造函数,每个实例都是新的实例。
反射泛型类
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);
}
}
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericClass`3");//三个泛型参数
//初始化方法一
GenericClass<string, int, DateTime> genericClass = new GenericClass<string, int, DateTime>();
object oGeneric = Activator.CreateInstance(type);
//初始化方法二
Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
object oGeneric = Activator.CreateInstance(typeMake);