01-反射

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

 

 

我们写的C#属于高级语言。通过编译器生成了exe或dll,在通过IL中间语言编译成CLR可识别的程序。最后形成机器码。在CLR识别dll的时候会发现dll上的matedata清单,比如有类、方法、属性、字段等。

反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata

一、如何去加载反射加载dll

使用 Assembly 加载,引用命名空间  System.Reflection

加载程序集有以下几种方式:

  1. Assembly assembly = Assembly.Load(“相对路径”);
  2. Assembly assembly = Assembly.LoadFile(“绝对路径”);
  3. 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 帮助类库。

posted @ 2020-03-10 22:31  delaywu  阅读(98)  评论(0)    收藏  举报