• 10分钟教你理解反射


    什么是反射?

    反射反射,程序员的快乐!在.Net领域程序设计中,反射是无处不在的,MVCASP.Net、各种ORMIOCAOP几乎所有的框架都离不开反射。反编译工具使用的底层技术用的不是反射,是一种逆向工程。

    反射(ReflectionSystem.Reflection),是.Net Framework提供的一个帮助类库,可以读取并使用Metadata中描述的数据信息。元数据(Metadata),描述了dll/exe里面的各种信息,又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。

    反射的优缺点:

    优点:动态—在不破坏原有程序的情况下,可对程序进行良好的扩展。Eg:我们有这样一需求,项目在最初的时候用的是Mysql数据库,由于项目情况变化需要更换成SqlServer数据库。面对这种项目的需求,传统的解决方法是在项目中添加新的SqlServer数据库访问代码,将数据库访问实现层更改为SqlServer,最后编译源代码并重新发布。

    传统解决方法示例伪代码如下:

    1                     IDBHelper iDBHelper = new MySqlHelper();
    2                     IDBHelper iDBHelper = new SqlServerHelper();
    3                     iDBHelper.Query();

    使用反射的示例代码:

     1 namespace ReflectionDemo
     2 {
     3     /// <summary>
     4     /// 反射工厂
     5     /// </summary>
     6     public class SimpleFactory
     7     {
     8         //读取配置文件
     9         private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
    10         //获取需要加载的dll名称
    11         private static string DllName = IDBHelperConfig.Split(',')[0]; 
    12         //获取需要的类型名称
    13         private static string TypeName = IDBHelperConfig.Split(',')[1];
    14         /// <summary>
    15         /// 通过反射动态加载与类型名称相匹配的实例
    16         /// </summary>
    17         /// <returns></returns>
    18         public static IDBHelper CreateInstance()
    19         {
    20             Assembly assembly = Assembly.Load(DllName);
    21             Type type = assembly.GetType(TypeName);
    22             object oDBHelper = Activator.CreateInstance(type);
    23             IDBHelper iDBHelper = oDBHelper as IDBHelper;
    24             return iDBHelper;
    25         }
    26     }
    27 }
      <add key="IDBHelperConfig" value="MySqlDb,MySqlDb.MySqlHelper"/>
                    IDBHelper iDBHelper = SimpleFactory.CreateInstance();
                    iDBHelper.Query();

    通过反射实现了程序的可配置,通过修改配置文件就可以自动切换实现类,实现类必须是事先已有的, 没有将实现类固定,而是通过配置文件执行,通过反射创建的。可扩展:完全不修改原有代码,只是增加新的实现、修改配置文件,就可以支持新功能。这就是反射的动态特性。

    缺点:使用麻烦、避开编译器检查导致运程序行时异常变多、性能问题。

    通过反射调用构造函数

      1 namespace SqlServerDb
      2 {
      3 
      4     /// <summary>
      5     /// 反射测试类
      6     /// </summary>
      7     public class ReflectionTest
      8     {
      9         #region Identity
     10         /// <summary>
     11         /// 无参构造函数
     12         /// </summary>
     13         public ReflectionTest()
     14         {
     15             Console.WriteLine("这里是{0}无参数构造函数", this.GetType());
     16         }
     17 
     18         /// <summary>
     19         /// 带参数构造函数
     20         /// </summary>
     21         /// <param name="name"></param>
     22         public ReflectionTest(string name)
     23         {
     24             Console.WriteLine("这里是{0} 有参数【string】构造函数", this.GetType());
     25         }
     26 
     27         public ReflectionTest(int id)
     28         {
     29             Console.WriteLine("这里是{0} 有参数【int】构造函数", this.GetType());
     30         }
     31         #endregion
     32 
     33         #region Method
     34         /// <summary>
     35         /// 无参方法
     36         /// </summary>
     37         public void Show1()
     38         {
     39             Console.WriteLine("这里是{0}的Show1", this.GetType());
     40         }
     41         /// <summary>
     42         /// 有参数方法
     43         /// </summary>
     44         /// <param name="id"></param>
     45         public void Show2(int id)
     46         {
     47 
     48             Console.WriteLine("这里是{0}的Show2", this.GetType());
     49         }
     50         /// <summary>
     51         /// 重载方法之一
     52         /// </summary>
     53         /// <param name="id"></param>
     54         /// <param name="name"></param>
     55         public void Show3(int id, string name)
     56         {
     57             Console.WriteLine("这里是{0}的Show3", this.GetType());
     58         }
     59         /// <summary>
     60         /// 重载方法之二
     61         /// </summary>
     62         /// <param name="name"></param>
     63         /// <param name="id"></param>
     64         public void Show3(string name, int id)
     65         {
     66             Console.WriteLine("这里是{0}的Show3_2", this.GetType());
     67         }
     68         /// <summary>
     69         /// 重载方法之三
     70         /// </summary>
     71         /// <param name="id"></param>
     72         public void Show3(int id)
     73         {
     74             Console.WriteLine("这里是{0}的Show3_3", this.GetType());
     75         }
     76         /// <summary>
     77         /// 重载方法之四
     78         /// </summary>
     79         /// <param name="name"></param>
     80         public void Show3(string name)
     81         {
     82             Console.WriteLine("这里是{0}的Show3_4", this.GetType());
     83         }
     84 
     85         /// <summary>
     86         /// 重载方法之五
     87         /// </summary>
     88         public void Show3()
     89         {
     90             Console.WriteLine("这里是{0}的Show3_1", this.GetType());
     91         }
     92 
     93         /// <summary>
     94         /// 私有方法
     95         /// </summary>
     96         /// <param name="name"></param>
     97         private void Show4(string name)
     98         {
     99             Console.WriteLine("这里是{0}的Show4", this.GetType());
    100         }
    101 
    102         /// <summary>
    103         /// 静态方法
    104         /// </summary>
    105         /// <param name="name"></param>
    106         public static void Show5(string name)
    107         {
    108             Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest));
    109         }
    110         #endregion
    111     }
    112 }
     1                 Assembly assembly = Assembly.Load("SqlServerDb");
     2                 Type type = assembly.GetType("SqlServerDb.ReflectionTest");
     3                 foreach (ConstructorInfo ctor in type.GetConstructors())
     4                 {
     5                     Console.WriteLine($"ctor.Name:{ctor.Name}");
     6                     foreach (var parameter in ctor.GetParameters())
     7                     {
     8                         Console.WriteLine($"ParameterType:{parameter.ParameterType},parameterName: {parameter.Name}");
     9                     }
    10                 }
    11                 object oTest1 = Activator.CreateInstance(type);
    12                 object oTest2 = Activator.CreateInstance(type, new object[] { 123 });
    13                 object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" });

     反射破坏单例

    1                 //反射破坏单例---就是反射调用私有构造函数
    2                 Assembly assembly = Assembly.Load("SqlServerDb");
    3                 Type type = assembly.GetType("SqlServerDb.Singleton");
    4                 Singleton singletonA = (Singleton)Activator.CreateInstance(type, true);
    5                 Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);
    6                 Console.WriteLine($"{object.ReferenceEquals(singletonA, singletonB)}");

    反射调用泛型类

    namespace SqlServerDb
    {
    
        /// <summary>
        /// 泛型测试类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="W"></typeparam>
        /// <typeparam name="X"></typeparam>
        public class GenericClass<T, W, X>
        {
            public GenericClass()
            {
                Console.WriteLine("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);
            }
        }
    
        /// <summary>
        /// 泛型测试方法
        /// </summary>
        public class GenericMethod
        {
    
            public GenericMethod()
            {
                Console.WriteLine("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);
            }
        }
    }
    1                 Assembly assembly = Assembly.Load("SqlServerDb");
    2                 Type type = assembly.GetType("SqlServerDb.GenericClass`3");
    3                 GenericClass<string, int, DateTime> genericClass = new GenericClass<string, int, DateTime>();
    4                 //genericClass.Show("12", 1, DateTime.Now);
    5                 //object oGeneric = Activator.CreateInstance(type);
    6                 Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
    7                 object oGeneric = Activator.CreateInstance(typeMake);

    反射调用泛型方法

                    Assembly assembly = Assembly.Load("SqlServerDb");
                    Type type = assembly.GetType("SqlServerDb.GenericMethod");
                    object oGeneric = Activator.CreateInstance(type);

    如果反射创建对象之后,知道方法名称,怎么样不做类型转换,直接调用方法?

     1    2                 Assembly assembly = Assembly.Load("SqlServerDb");
     3                 Type type = assembly.GetType("SqlServerDb.ReflectionTest");
     4                 object oTest = Activator.CreateInstance(type);
     5                 foreach (var method in type.GetMethods())
     6                 {
     7                     Console.WriteLine(method.Name);
     8                     foreach (var parameter in method.GetParameters())
     9                     {
    10                         Console.WriteLine($"{parameter.Name}  {parameter.ParameterType}");
    11                     }
    12                 }
    13                 {
    14                     ReflectionTest reflection = new ReflectionTest();
    15                     reflection.Show1();
    16                 }
    17                 {
    18                     MethodInfo method = type.GetMethod("Show1");
    19                     //if()
    20                     method.Invoke(oTest, null);
    21                 }
    22                 {
    23                     MethodInfo method = type.GetMethod("Show2");
    24                     method.Invoke(oTest, new object[] { 123 });
    25                 }
    26                 {
    27                     MethodInfo method = type.GetMethod("Show3", new Type[] { });
    28                     method.Invoke(oTest, null);
    29                 }
    30                 {
    31                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });
    32                     method.Invoke(oTest, new object[] { 123 });
    33                 }
    34                 {
    35                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });
    36                     method.Invoke(oTest, new object[] { "一生为你" });
    37                 }
    38                 {
    39                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
    40                     method.Invoke(oTest, new object[] { 234, "心欲无痕" });
    41                 }
    42                 {
    43                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
    44                     method.Invoke(oTest, new object[] { "PHS", 345 });
    45                 }
    46                 {
    47                     MethodInfo method = type.GetMethod("Show5");
    48                     method.Invoke(oTest, new object[] { "张中魁" });//静态方法实例可以要
    49                 }
    50                 {
    51                     MethodInfo method = type.GetMethod("Show5");
    52                     method.Invoke(null, new object[] { "张中魁" });//静态方法实例也可以不要
    53                 }

    反射调用私有方法

    1             {
    2                 //调用私有方法
    3                 Console.WriteLine("&&&&&&&&&&&&&&&&&&&&私有方法&&&&&&&&&&&&&&&&&&&");
    4                 Assembly assembly = Assembly.Load("SqlServerDb");
    5                 Type type = assembly.GetType("SqlServerDb.ReflectionTest");
    6                 object oTest = Activator.CreateInstance(type);
    7                 var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
    8                 method.Invoke(oTest, new object[] { "我是老王" });
    9             }

    反射调用泛型方法

                    Assembly assembly = Assembly.Load("SqlServerDb");
                    Type type = assembly.GetType("SqlServerDb.GenericMethod");
                    object oGeneric = Activator.CreateInstance(type);
                    foreach (var item in type.GetMethods())
                    {
                        Console.WriteLine(item.Name);
                    }
                    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 });

    反射调用泛型方法加泛型类

    1                 Assembly assembly = Assembly.Load("SqlServerDb");
    2                 //在获取类型的同时通过MakeGenericType指定泛型的参数类型
    3                 Type type = assembly.GetType("SqlServerDb.GenericDouble`1").MakeGenericType(typeof(int));
    4                 object oObject = Activator.CreateInstance(type);
    5                 MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(DateTime));
    6                 method.Invoke(oObject, new object[] { 345, "感谢有梦", DateTime.Now });
  • 相关阅读:
    CentOS7基础优化与常用配置
    MHA+binlogserver+VIP+sendreport 高可用架构
    GTID主从复制
    主从复制故障处理
    主从复制
    mysql 配置文件
    通用二进制安装mysql-5.7.28(无坑)
    css动画 文字闪烁效果
    cmd命令提示符大全(干货)
    JS实现手机摇一摇功能
  • 原文地址:https://www.cnblogs.com/netlws/p/11001218.html
Copyright © 2020-2023  润新知