コード例 #1
0
ファイル: Program.cs プロジェクト: wangongshen/Reflection
        static void Main(string[] args)
        {
            try
            {
                #region 创建连接
                {
                    Console.WriteLine("==========创建连接=============");
                    //IDBHelper iDBHelper = new MySqlHelper();
                    IDBHelper iDBHelper = new SqlServerHelper();

                    //当MySqlHelper换成SqlServerHelper 就必学修改现有的代码,重新编译然后发布,为了提高效率我们可以利用反射来解决这一问题。
                }
                #endregion

                #region 加载DLL
                {
                    Console.WriteLine("==========加载DLL==========");
                    //根据名称加载程序集
                    //Assembly assembly = Assembly.Load("Gs.DB.MySql");
                    //根据完整路径加载程序集
                    //Assembly assembly1 = Assembly.LoadFile(@"‪C:\Users\wango\source\repos\Reflection\Gs.DB.MySql\bin\Debug\Gs.DB.MySql.dll");
                    //根据名称加载程序集
                    Assembly assembly2 = Assembly.LoadFrom("Gs.DB.SqlServer.dll");
                    //根据完整路径加载程序集
                    //Assembly assembly3 = Assembly.LoadFrom(@"C:\Users\wango\source\repos\Reflection\Gs.DB.MySql\bin\Debug\Gs.DB.MySql.dll");
                    ///**
                    ///以上四个assembly获取的结果都是一样的
                    ///看起来LoadFile和LoadFrom作用是一样,他们两个有什么区别呢?
                    ///LoadFile加载dll文件时只会加载指定的dll文件,不会加载与指定dll文件相关的dll文件,而LoadFrom则会加载与指定dll文件相关的dll文件
                    ///LoadFrom加载dll文件时会先检查前面是否已经加载过相同名称的dll,如果载入过相同的dll那就不能再载入,而LoadFile不检查,会直接覆盖之前相同名称的dll文件
                    ///

                    ///

                    foreach (var type in assembly2.GetTypes())
                    {
                        Console.WriteLine("类:" + type.Name);
                        foreach (var method in type.GetMethods())
                        {
                            Console.WriteLine(type.Name + "类中的方法:" + method.Name);
                        }
                    }
                }
                #endregion

                #region 加载DLL并创建对象
                {
                    Console.WriteLine("*****************加载DLL并创建对象、调用方法********************");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");                    //1 动态加载
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.SqlServerHelper"); //2 获取程序集下的指定类
                    foreach (var member in type.GetMembers())
                    {
                        //遍历类中的方法
                        Console.WriteLine("方法名:" + member.Name);
                    }
                    //object oDBHelper = Activator.CreateInstance(type); //创建对象
                    //oDBHelper.Say(); //调用方法,实际上oDBHelper是有SqlServerHelper()这个方法,只不过编译器不通过,解决这个问题可以用dynamic来收
                    dynamic dDBHelper = Activator.CreateInstance(type);
                    dDBHelper.Say(); //dynamic编译器不检查,方法拼写一定要写对

                    //不使用dynamic,转换类型也可以
                    object    oDBHelper       = Activator.CreateInstance(type); //创建对象
                    IDBHelper SqlServerHelper = oDBHelper as IDBHelper;
                    SqlServerHelper.Say();                                      //调用方法,实际上oDBHelper是有SqlServerHelper()这个方法,只不过编译器不通过,解决这个问题可以用dynamic来收
                }
                #endregion 封装之后
                {
                    Console.WriteLine("*****************封装之后********************");
                    IDBHelper iDBHelper = SimpleFactory.CreateInstance();
                    iDBHelper.Say();
                    //程序的可配置,通过修改配置文件就可以自动切换,实现类必须是事先已有的,而且在目录下面,没有写死类型,而是通过配置文件执行,反射创建的
                    //可扩展:完全不修改原有代码,只是增加新的实现,copy,修改配置文件,就可以支持新功能
                    //反射的动态加载和动态创建对象  以及配置文件结合
                }

                #region 调用带参方法
                {
                    //Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
                    //Type type = assembly.GetType("Ruanmou.DB.SqlServer.ReflectionTest");
                    //foreach (ConstructorInfo ctor in type.GetConstructors())
                    //{
                    //    Console.WriteLine(ctor.Name);
                    //    foreach (var parameter in ctor.GetParameters())
                    //    {
                    //        Console.WriteLine(parameter.ParameterType);
                    //    }
                    //}
                    //object oTest1 = Activator.CreateInstance(type);
                    //object oTest2 = Activator.CreateInstance(type, new object[] { 123 });
                    //object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" });

                    Console.WriteLine("*****************调用带参方法********************");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.ReflectionTest");
                    foreach (ConstructorInfo ctor in type.GetConstructors())
                    {
                        //获取类中的构造方法
                        Console.WriteLine("111:" + ctor.Name);
                        foreach (var parameter in ctor.GetParameters())
                        {
                            //返回构造方法的参数
                            Console.WriteLine("222:" + parameter.ParameterType);
                        }
                    }
                    object oTest1 = Activator.CreateInstance(type);
                    object oTest2 = Activator.CreateInstance(type, new object[] { 960927 });
                    object oTest3 = Activator.CreateInstance(type, new object[] { "调用带参方法" });
                }
                #endregion

                #region 反射破坏单例
                {
                    Console.WriteLine("********************反射破坏单例********************");
                    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)}");

                    //反射破坏单例---因为构造方法是用private修饰的,防止外部调用,但是反射不受限制
                    Assembly  assembly   = Assembly.Load("Gs.DB.SqlServer");
                    Type      type       = assembly.GetType("Gs.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)}");
                }

                #endregion 反射调用泛型
                {
                    Console.WriteLine("********************反射调用泛型********************");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.GenericClass`3"); //3表示GenericClass有3个参数

                    Type    typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
                    dynamic oGeneric = Activator.CreateInstance(typeMake);
                    oGeneric.ShowA();
                    //MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(string), typeof(string));
                    //method.Invoke(oGeneric, new object[] { "123","456","789" });
                }
                #region   做类型转换调用
                {
                    //如果反射创建对象之后,知道方法名称,怎么样不做类型转换,直接调用方法?
                    //反射创建了对象实例---有方法的名称--反射调用方法
                    //dll名称---类型名称---方法名称---我们就能调用方法
                    //MVC就是靠的这一招---调用Action
                    //http://localhost:9099/home/index  经过路由解析---会调用--HomeController--Index方法
                    //浏览器输入时只告诉了服务器类型名称和方法名称,肯定是反射的
                    //MVC在启动时会先加载--扫描全部的dll--找到全部的Controller--存起来--请求来的时候,用Controller来匹配的---dll+类型名称
                    //1 MVC局限性的--Action重载--反射是无法区分---只能通过HttpMethod+特性httpget/httppost
                    //2 AOP--反射调用方法,可以在前后插入逻辑
                    Console.WriteLine("********************不做类型转换调用********************");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.ReflectionTest");
                    object   oTest    = Activator.CreateInstance(type);

                    foreach (var method in type.GetMethods())
                    {
                        //获取类中的方法名
                        Console.WriteLine("方法名:" + method.Name);
                        foreach (var parameter in method.GetParameters())
                        {
                            //获取方法中的参数
                            Console.WriteLine(method.Name + "方法中的参数:" + parameter.Name + "===" + parameter.ParameterType);
                        }
                    }
                    {
                        ReflectionTest reflection = new ReflectionTest();
                        Console.WriteLine("普通调用");
                        reflection.Show1();
                    }
                    {
                        MethodInfo method = type.GetMethod("Show1");
                        Console.WriteLine("反射调用");
                        method.Invoke(oTest, null);
                    }
                    {
                        MethodInfo method = type.GetMethod("Show2");
                        Console.WriteLine("反射调用有参方法");
                        method.Invoke(oTest, new object[] { 123 });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { });
                        Console.WriteLine("反射调用重载无参方法Show3");
                        method.Invoke(oTest, null);
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });
                        method.Invoke(oTest, new object[] { 1700 });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });
                        method.Invoke(oTest, new object[] { "2020年2月23日17:02:00" });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
                        method.Invoke(oTest, new object[] { 1702, "2020年2月23日17:02:38" });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
                        method.Invoke(oTest, new object[] { "2020年2月23日17:04:02", 1704 });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show5");
                        method.Invoke(oTest, new object[] { "2020年2月23日17:04:32" });
                    }
                }
                #endregion 调用私有方法
                {
                    //调用私有方法
                    Console.WriteLine("&&&&&&&&&&&&&&&&&&&&私有方法&&&&&&&&&&&&&&&&&&&");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.ReflectionTest");
                    object   oTest    = Activator.CreateInstance(type);
                    var      method   = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
                    //var method = type.GetMethod("Show4");
                    method.Invoke(oTest, new object[] { "2020年2月23日17:13:08" });
                }
                #region
                {
                    Console.WriteLine("********************调用泛型方法********************");
                    Assembly assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type     type     = assembly.GetType("Gs.DB.SqlServer.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[] { 1920, "2020年2月23日19:20:25", DateTime.Now });
                }
                #endregion
                {
                    Console.WriteLine("********************调用泛型类中的泛型方法********************");
                    Assembly   assembly = Assembly.Load("Gs.DB.SqlServer");
                    Type       type     = assembly.GetType("Gs.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[] { 1927, "2020年2月23日19:42:22", DateTime.Now });
                }
                #region
                {
                    Console.WriteLine("*****************Common*******************");
                    People people = new People();
                    people.Id          = 001;
                    people.Name        = "孙悟空";
                    people.Description = "我是齐天大圣";
                    Console.WriteLine($"people.Id={people.Id}");
                    Console.WriteLine($"people.Name={people.Name}");
                    Console.WriteLine($"people.Description={people.Description}");
                }
                #endregion 反射赋值
                {
                    //1 get 反射展示是有意义的--反射遍历,可以不用改代码
                    //2 set 感觉好像没啥用
                    Console.WriteLine("*****************反射赋值*******************");
                    Type   type    = typeof(People);
                    object oPeople = Activator.CreateInstance(type);
                    foreach (var prop in type.GetProperties())
                    {
                        Console.WriteLine("类:" + type.Name + ";属性:" + prop.Name + ";值:" + prop.GetValue(oPeople));
                        Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}");
                        if (prop.Name.Equals("Id"))
                        {
                            prop.SetValue(oPeople, 234);
                        }
                        else if (prop.Name.Equals("Name"))
                        {
                            prop.SetValue(oPeople, "猪八戒");
                        }
                        Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(oPeople)}");
                    }
                    foreach (var field in type.GetFields())
                    {
                        Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oPeople)}");
                        if (field.Name.Equals("Description"))
                        {
                            field.SetValue(oPeople, "我是天蓬元帅");
                        }
                        Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(oPeople)}");
                    }
                }
                #region 动态查询数据库
                {
                    Console.WriteLine("******************动态查询数据库*********************");
                    SqlServerHelper helper  = new SqlServerHelper();
                    Company         company = helper.Find <Company>(1);
                    User            user    = helper.Find <User>(1);
                }
                #endregion 测试性能
                {
                    Console.WriteLine("*******************测试性能*******************");
                    Monitor.Show();
                }
                #region

                #endregion
            }
            catch (Exception e)
            {
                Console.WriteLine("错误信息:" + e.Message);
            }
            Console.WriteLine("运行完毕");
            Console.ReadLine();
        }
コード例 #2
0
ファイル: Program.cs プロジェクト: junchenglai/csharp
        static void Main(string[] args)
        {
            try
            {
                #region Common
                {
                    Console.WriteLine("*************** Common *****************");
                    IDBHelper iDBHelper = new MySqlHelper();
                    iDBHelper.Query();
                }
                #endregion

                #region Reflection
                {
                    Console.WriteLine("************* Reflection ***************");
                    Assembly assembly1 = Assembly.Load("Reflection.DB.MySql"); // 1 动态加载 一个完整的 dll 名称不需要后缀(从 exe 所在的路径进行查找)
                    // Assembly assembly2 = Assembly.LoadFile(@"E:\GitHub\csharp\02Reflection\Reflection.DB.MySql\bin\Debug\netstandard2.0\Reflection.DB.MySql.dll"); // 必须要完整路径
                    // Assembly assembly3 = Assembly.LoadFrom("Reflection.DB.MySql.dll"); // 当前路径
                    // Assembly assembly4 = Assembly.LoadFrom(@"E:\GitHub\csharp\02Reflection\Reflection.DB.MySql\bin\Debug\netstandard2.0\Reflection.DB.MySql.dll"); //完整路径

                    foreach (var type in assembly1.GetTypes())
                    {
                        Console.WriteLine(type.Name);
                        foreach (var method in type.GetMethods())
                        {
                            Console.WriteLine(method.Name);
                        }
                    }
                }
                #endregion
                {
                    Assembly assembly = Assembly.Load("Reflection.DB.MySql");                // 1 动态加载
                    Type     type     = assembly.GetType("Reflection.DB.MySql.MySqlHelper"); // 2 获取类型 完整类型名称

                    object oDBHelper = Activator.CreateInstance(type);                       // 3 创建对象
                    // oDBHelper.Query(); // 无法直接调用方法,编译器不允许
                    // C# 是一种强类型语言,静态语言,编译时就确定好类型保证安全

                    dynamic dDBHelper = Activator.CreateInstance(type);
                    dDBHelper.Query();                            // dynamic 跳过编译器检查,运行时才检查

                    IDBHelper iDBHelper = oDBHelper as IDBHelper; // 4 类型转换 不报错,类型不对就返回 null
                    iDBHelper.Query();                            // 5 方法调用
                }

                {
                    Console.WriteLine("**** Reflection + Factory + Config ****");
                    IDBHelper iDBHelper = SimpleFactory.CreaterInstance();
                    iDBHelper.Query();
                    // 程序是可配置的,通过修改配置就可以自动切换
                    // 没有写死类型,而是通过配置文件执行,反射创建的
                    // 实现类必须是事先已有的,而且在目录下面

                    // 可扩展:完全不修改原有代码,只是增加新的实现、复制、修改配置,则可以支持新功能
                    // 反射的动态加载和动态创建对象,以及配置文件结合
                }

                {
                    Console.WriteLine("********* ctor + parameter **********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.ReflectionTest");
                    IDBHelper iDBHelper1 = Activator.CreateInstance(type) as IDBHelper;
                    IDBHelper iDBHelper2 = Activator.CreateInstance(type, new object[] { 123 }) as IDBHelper;
                    IDBHelper iDBHelper3 = Activator.CreateInstance(type, new object[] { "oTest" }) as IDBHelper;

                    foreach (ConstructorInfo ctor in type.GetConstructors())
                    {
                        Console.WriteLine(ctor.Name);
                        foreach (var parameter in ctor.GetParameters())
                        {
                            Console.WriteLine(parameter.ParameterType);
                        }
                    }
                }

                {
                    Console.WriteLine("************ Singleton *************");
                    Singleton singleton  = Singleton.GetInstance();
                    Singleton singleton1 = Singleton.GetInstance();
                    Console.WriteLine(ReferenceEquals(singleton, singleton1));

                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.Singleton");
                    //Singleton singletonA = Activator.CreateInstance(type) as Singleton; // error: 无法实例化单例

                    // 反射破坏单例 —— 就是反射调用私有构造函数
                    Singleton singletonA = Activator.CreateInstance(type, true) as Singleton;
                    Singleton singletonB = Activator.CreateInstance(type, true) as Singleton;
                    Console.WriteLine(ReferenceEquals(singletonA, singletonB));
                }

                {
                    Console.WriteLine("********** GenericClass ***********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.GenericClass`3");
                    // object oGeneric = Activator.CreateInstance(type); // error: 泛型无法直接实例化
                    Type   typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
                    object oGeneric = Activator.CreateInstance(typeMake);
                }

                #region 泛型方法
                {
                    Console.WriteLine("********** GenericMethod ***********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.GenericMethod");
                    object oGeneric = Activator.CreateInstance(type);
                    foreach (MethodInfo item in type.GetMethods())
                    {
                        Console.WriteLine(item.Name);
                    }
                    MethodInfo method    = type.GetMethod("Show");
                    MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
                    methodNew.Invoke(oGeneric, new object[] { 123, "John", DateTime.Now });
                }
                {
                    Console.WriteLine("******* GenericClass&Method ********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.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[] { 123, "John", DateTime.Now });
                }
                #endregion

                {
                    // 反射创建对象后,知道方法名称,可以直接调用而不需做类型转换
                    // 反射创建了对象实例——知道方法的名称——反射调用方法
                    // dll 名称——类型名称——方法名称——我们就能调用方法
                    // MVC 依赖这种模式——调用 Action
                    // http://localhost:9099/home/index 通过路由解析——会调用 HomeController——Index方法
                    // 相当于浏览器输入时告诉了服务器类型的名称和方法的名称
                    // MVC 加载时会先扫描所有 dll —— 找到所有的控制器 —— 请求来时用Controller 来匹配
                    // 1 MVC的局限性:Action 重载时,反射是无法区分的,只能通过 HttpMethod + 特性 HttpGet/HttpPost 等
                    // 2 AOP 反射调用方法,可以在前后插入逻辑
                    Console.WriteLine("********** GenericMethod ***********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.ReflectionTest");
                    object oTest = Activator.CreateInstance(type);
                    // 直接调用 Show1 方法
                    foreach (var method in type.GetMethods())
                    {
                        Console.WriteLine(method.Name);
                        foreach (var parameter in method.GetParameters())
                        {
                            Console.WriteLine($"{parameter.Name} {parameter.ParameterType}");
                        }
                    }
                    {
                        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[] { "John" });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
                        method.Invoke(oTest, new object[] { 123, "John" });
                    }
                    {
                        MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
                        method.Invoke(oTest, new object[] { "John", 123 });
                    }
                    {
                        // 静态方法实例可要可不要
                        MethodInfo method = type.GetMethod("Show5");
                        method.Invoke(oTest, new object[] { "John" });
                        method.Invoke(null, new object[] { "John" });
                    }
                }

                #region 反射调用私有方法
                {
                    Console.WriteLine("********* 反射调用私有方法 *********");
                    Type type = Assembly.Load("Reflection.DB.SqlServer")
                                .GetType("Reflection.DB.SqlServer.ReflectionTest");
                    object oTest   = Activator.CreateInstance(type);
                    var    method  = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
                    object oReturn = method.Invoke(oTest, new object[] { "John" });
                }
                #endregion

                #region
                {
                }
                #endregion
            }
            catch (Exception)
            {
                throw;
            }
        }