01-反射
在C#中反射是无处不在的。在介绍反射之前我想用一张图来说明一下:

我们写的C#属于高级语言。通过编译器生成了exe或dll,在通过IL中间语言编译成CLR可识别的程序。最后形成机器码。在CLR识别dll的时候会发现dll上的matedata清单,比如有类、方法、属性、字段等。
反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata
一、如何去加载反射加载dll
使用 Assembly 加载,引用命名空间 System.Reflection
加载程序集有以下几种方式:
- Assembly assembly = Assembly.Load(“相对路径”);
- Assembly assembly = Assembly.LoadFile(“绝对路径”);
- Assembly assembly = Assembly.LoadFrom(“当前路径也可绝对路径”);
如下所示:
Assembly assembly = Assembly.Load("Ruanmou.DB.MySql");
Assembly assembly1 = Assembly.LoadFile(@"D:\ruanmou\online12\20181212Advanced12Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.MySql.dll");//完整路径
Assembly assembly2 = Assembly.LoadFrom("Ruanmou.DB.MySql.dll");//当前路径
Assembly assembly3 = Assembly.LoadFrom(@"D:\ruanmou\online12\20181212Advanced12Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.MySql.dll");//当前路径
二、如何通过反射创建实例
ReflectionTest 类:
/// <summary>
/// 反射测试类
/// </summary>
public class ReflectionTest
{
#region Identity
/// <summary>
/// 无参构造函数
/// </summary>
public ReflectionTest()
{
Console.WriteLine("这里是{0}无参数构造函数", this.GetType());
}
/// <summary>
/// 带参数构造函数
/// </summary>
/// <param name="name"></param>
public ReflectionTest(string name)
{
Console.WriteLine("这里是{0} 有参数构造函数", this.GetType());
}
public ReflectionTest(int id)
{
Console.WriteLine("这里是{0} 有参数构造函数", this.GetType());
}
#endregion
#region Method
/// <summary>
/// 无参方法
/// </summary>
public void Show1()
{
Console.WriteLine("这里是{0}的Show1", this.GetType());
}
/// <summary>
/// 有参数方法
/// </summary>
/// <param name="id"></param>
public void Show2(int id)
{
Console.WriteLine("这里是{0}的Show2", this.GetType());
}
/// <summary>
/// 重载方法之一
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
public void Show3(int id, string name)
{
Console.WriteLine("这里是{0}的Show3", this.GetType());
}
/// <summary>
/// 重载方法之二
/// </summary>
/// <param name="name"></param>
/// <param name="id"></param>
public void Show3(string name, int id)
{
Console.WriteLine("这里是{0}的Show3_2", this.GetType());
}
/// <summary>
/// 重载方法之三
/// </summary>
/// <param name="id"></param>
public void Show3(int id)
{
Console.WriteLine("这里是{0}的Show3_3", this.GetType());
}
/// <summary>
/// 重载方法之四
/// </summary>
/// <param name="name"></param>
public void Show3(string name)
{
Console.WriteLine("这里是{0}的Show3_4", this.GetType());
}
/// <summary>
/// 重载方法之五
/// </summary>
public void Show3()
{
Console.WriteLine("这里是{0}的Show3_1", this.GetType());
}
/// <summary>
/// 私有方法
/// </summary>
/// <param name="name"></param>
private void Show4(string name)
{
Console.WriteLine("这里是{0}的Show4", this.GetType());
}
/// <summary>
/// 静态方法
/// </summary>
/// <param name="name"></param>
public static void Show5(string name)
{
Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest));
}
#endregion
}
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest");
//创建无参实例
object oTest1 = Activator.CreateInstance(type);
//创建有参实例
object oTest2 = Activator.CreateInstance(type, new object[] { 123 });
以上都是普通类的实例化。那么泛型类的实例化是如何实现的。
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);
}
}
实现方式:
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericClass`3");
Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
object oGeneric = Activator.CreateInstance(typeMake);
三、如何通过反射调用方法
上面我们拿到了 ReflectionTest 的实例。我们现在调用实例里的方法如下:
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest");
object oTest = Activator.CreateInstance(type);
{
MethodInfo method = type.GetMethod("Show1");
method.Invoke(oTest, null);
}
{
MethodInfo method = type.GetMethod("Show2");
method.Invoke(oTest, new object[] { 123 });
}
{
MethodInfo method = type.GetMethod("Show3", new Type[] { });
method.Invoke(oTest, null);
}
{
MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });
method.Invoke(oTest, new object[] { 123 });
}
{
MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });
method.Invoke(oTest, new object[] { "一生为你" });
}
{
MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
method.Invoke(oTest, new object[] { 234, "心欲无痕" });
}
{
MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
method.Invoke(oTest, new object[] { "PHS", 345 });
}
{
MethodInfo method = type.GetMethod("Show5");
method.Invoke(oTest, new object[] { "张中魁" });//静态方法实例可以要
}
{
MethodInfo method = type.GetMethod("Show5");
method.Invoke(null, new object[] { "张中魁" });//静态方法实例也可以不要
}
通过反射调用私有方法:
var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(oTest, new object[] { "我是老王" });
如何调用普通类中的泛型方法:
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericMethod");
object oGeneric = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("Show");
var methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
object oReturn = methodNew.Invoke(oGeneric, new object[] { 123, "董小姐", DateTime.Now });
如何调用泛型类中的泛型方法:
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
Type type = assembly.GetType("Ruanmou.DB.SqlServer.GenericDouble`1").MakeGenericType(typeof(int));
object oObject = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(DateTime));
method.Invoke(oObject, new object[] { 345, "感谢有梦", DateTime.Now });
下一篇介绍 :利用反射封装ADO.NET 帮助类库。
PYTHON

浙公网安备 33010602011771号