zoukankan      html  css  js  c++  java
  • 反射由浅入深了解学习(一)

    一,反射三个步骤
    1, 加载dll获取的程序集
    2,通过加载的dll得到的程序集和类型的全名,得到想要的类型
    3,使用指定类型的默认构造函数来创建该类型的实例

    二,代码结构如下图

    二,Program.cs代码如下:

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ReflectionDemo
    {
        class Program
        {
    
            private static string config = ConfigurationManager.AppSettings["DbConfig"]; //反射的配置
            static void Main(string[] args)
            {
                Assembly assembly = Assembly.Load(config.Split(',')[1]); //加载dll获取的程序集
                Type type = assembly.GetType(config.Split(',')[0]); //通过加载的dll得到的程序集和类型的全名,得到想要的类型
                //显示加载程序集的路径
                foreach (Module item in assembly.GetModules())
                {
                    Console.WriteLine("DLL地址{0}", item.FullyQualifiedName);
                }
                ///显示加载程序集的名称
                foreach (Type item in assembly.GetTypes())
                {
                    Console.WriteLine("DLL名称{0}", item.FullName);
                }
                ///显示所有方法
                foreach (MethodInfo item in type.GetMethods())
                {
                    Console.WriteLine("方法名称{0}", item.Name);
                }
    
                //创建对象,使用指定类型的默认构造函数来创建该类型的实例
                object oDbHelper = Activator.CreateInstance(type);
    
                ///反射调用无参数方法
                ///PS修改BLL库需要拷贝到当前的控制台程序
                MethodInfo query1 = type.GetMethod("Query");
                query1.Invoke(oDbHelper, null);
    
                //发现不明确匹配,因为Query1方法重载了,跟MVC中的找视图和方法时报错一样,多个请求路由存在多个相同命名视图逻辑一样报错
                //MethodInfo query8 = type.GetMethod("Query1");
                //query8.Invoke(oDbHelper, new object[] { "string参数" });
    
                ///反射带参数方法
                MethodInfo query2 = type.GetMethod("Query1", new Type[] { typeof(string) });
                query2.Invoke(oDbHelper, new object[] { "string参数" });
    
                MethodInfo query3 = type.GetMethod("Query1", new Type[] { typeof(int) });
                query3.Invoke(oDbHelper, new object[] { 111 });
    
                /// PS:对私有方法和静态实例不建议用反射来获取实现,破坏了设计的原则,但是测试和观看源码时可以使用
                //私有方法的反射
                MethodInfo query4 = type.GetMethod("QueryPrivate", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
                query4.Invoke(oDbHelper, null);
    
                //私有带参数方法的反射
                MethodInfo query5 = type.GetMethod("QueryPrivateParam", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(int) }, null);
                query5.Invoke(oDbHelper, new object[] { 444 });
    
                MethodInfo query6 = type.GetMethod("QueryPrivateParam", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
                query6.Invoke(oDbHelper, new object[] { "string参数" });
    

            //对单例模式创建实例
            //Type Singleton = assembly.GetType("BLLExt.Singleton");
            ////object ob = Activator.CreateInstance(Singleton); //报错:没有为该对象定义无参数的构造函数
            //object ob = Activator.CreateInstance(Singleton,true);

    
                Console.ReadKey();
            }
        }
    }

    SqlHelper.cs代码如下:

    using IBLL;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace BLL
    {
        public class SqlHelper: IDbHelper
        {
            public SqlHelper()
            {
                Console.WriteLine("{0}被构造", this.GetType().Name);
            }
    
    
            public void Query()
            {
                Console.WriteLine("{0}.Query", this.GetType().Name);
            }
            public void Query1(string obj)
            {
                Console.WriteLine("{0}---{1}.Query", obj, this.GetType().Name);
            }
            public void Query1(int obj)
            {
                Console.WriteLine("{0}---{1}.Query", obj, this.GetType().Name);
            }
            private void QueryPrivate()
            {
                Console.WriteLine("{0}.QueryPrivate", this.GetType().Name);
            }
            private void QueryPrivateParam(string obj)
            {
                Console.WriteLine("{0}---{1}.QueryPrivateParam", obj, this.GetType().Name);
            }
            private void QueryPrivateParam(int obj)
            {
                Console.WriteLine("{0}---{1}.QueryPrivateParam", obj, this.GetType().Name);
            }
        }
    }

    IDbHelper.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace IBLL
    {
        public interface IDbHelper
        {
             void Query();
        }
    }

    App.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
      <appSettings>
        <add key="DbConfig" value="BLL.SqlHelper,BLL"/>
        <!--<add key="DbConfig" value="BLLExt.MySqlHelper,BLLExt"/>-->
      </appSettings>
    </configuration>

     三,如上代码,我们需要注意的是:

    1,创建反射的步骤
    2,反射调用无参数方法和有参方法的区别
    3,重载方法的反射需标明参数的类型,如下:

    //发现不明确匹配,因为Query1方法重载了,跟MVC中的找视图和方法时报错一样,多个请求路由存在多个相同命名视图逻辑一样报错
    MethodInfo query8 = type.GetMethod("Query1");
    query8.Invoke(oDbHelper, new object[] { "string参数" });

    以上报错,重载方法无参数正确写法

    //重载方法无参数反射的使用
    MethodInfo query9 = type.GetMethod("Query1", new Type[] { });
    query9.Invoke(oDbHelper, null);

    4,对私有方法的反射

    四,反射的扩展

    1,对单例的反射

     Singleton.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace BLL
    {
        public class Singleton
        {
            public static Singleton _Instance = new Singleton();
            private Singleton() {
                Console.WriteLine("{0}被构造了",this.GetType().Name);
            }
        }
    }

    反射代码

    //对单例模式创建实例
    Type Singleton = assembly.GetType("BLLExt.Singleton");
     ////object ob = Activator.CreateInstance(Singleton); //报错:没有为该对象定义无参数的构造函数
    object ob = Activator.CreateInstance(Singleton,true);

     2,反射类库的切换,通过反射获取的实例都是不需要引用的,如下图,没有引用bll

    那我们怎么动态切换库呢?再用反射时只需要更改配置文件App.config即可,如配置

    更改配置为,BLLExt.MySqlHelper,输出结果是不一样的

    PS :但是每次我们修改BLL和BLLExt库时都要将其生成的DLL手动拷贝到ReflectionDemo的bin文件下,原因是:ReflectionDemo没有引用这两个库,重新生成不会生成到改目录的bin目录下

    反射由浅入深了解学习(二)

  • 相关阅读:
    图的深度优先搜索(递归和非递归c++实现)
    第十届蓝桥杯大赛软件类省赛 迷宫问题题解
    第十届蓝桥杯大赛软件类省赛研究生组 试题D:最短路
    第十届蓝桥杯大赛软件类省赛研究生组 试题H:修改数组
    Redis设计与实现书中勘误-sdstrim函数解释错误
    Clion 引入libevent Undefined symbols for architecture x86_64: "
    RabbitMQ Linux 下 安装
    kafka基本使用
    2种方法改变String 值
    Maven学习笔记-1
  • 原文地址:https://www.cnblogs.com/May-day/p/10865516.html
Copyright © 2011-2022 走看看