• C#中反射的使用(How to use reflect in CSharp)(2)


    在上一篇里,我们叨逼了好多如何获取到程序集里的对象,但是对象有了,还不知道怎么调,OK,下面开始干这个对象:

    首先,我们对上一篇的对象做了一些修改,以适应多种情况:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 
     5 namespace PersonMoudle
     6 {
     7     public class Person
     8     {
     9         public Person()
    10         {
    11             Name = "Sirius";
    12             Age = 25;
    13             Height = 172;
    14             Sex = "Middle";
    15         }
    16         public Person(string name, int age, float height, string sex)
    17         {
    18             Name = name;
    19             Age = age;
    20             Height = height;
    21             Sex = sex;
    22         }
    23 
    24         public string Name { get; set; }
    25         public int Age { get; set; }
    26         public float Height { get; set; }
    27         public string Sex { get; set; }
    28 
    29         #region Void
    30         /// <summary>
    31         /// 说话方法
    32         /// </summary>
    33         /// <param name="words"></param>
    34         public void Speak(string words)
    35         {
    36             Console.WriteLine(words);
    37         }
    38         /// <summary>
    39         /// 打电话方法
    40         /// </summary>
    41         /// <param name="telto">打给谁</param>
    42         /// <param name="words">说什么</param>
    43         public void TelSomeone(string telto, string words)
    44         {
    45             Console.WriteLine("Hi " + telto + ", This is sirius speaking! " + words);
    46         }
    47 
    48         /// <summary>
    49         /// 叫爹方法
    50         /// </summary>
    51         public void SayHi()
    52         {
    53             Console.WriteLine("Hi, Dad!");
    54         }
    55         #endregion
    56 
    57         private string GetMyName()
    58         {
    59             return Name.Trim();
    60         }
    61 
    62         public string GetMySex()
    63         {
    64             return Sex;
    65         }
    66 
    67         public List<string> BeenCity()
    68         {
    69             return new List<string>
    70             {
    71                 "Beijing",
    72                 "Jinan",
    73                 "NewYork"
    74             };
    75         }
    76 
    77         public List<string> BennCity(int count)
    78         {
    79             return new List<string>
    80             {
    81                 "Beijing",
    82                 "Jinan",
    83                 "NewYork"
    84             }.Take(count).ToList();
    85         }
    86     }
    87 }
    Person类

    然后,我们在另一个项目里load这个dll,用反射调用有参数、无参数的构造函数/有参数、无参数的方法,以及拿到他们的返回值:

     1 using System;
     2 using System.Linq;
     3 using System.Reflection;
     4 
     5 namespace ReflectionTest
     6 {
     7     class Program
     8     {
     9         static void Main(string[] args)
    10         {
    11 
    12             /*
    13              How to use reflect to invoke a method, we've these steps:
    14              * 1.Get assembly of your moudle
    15              * 2.Get the type that you want to use(here is Person type)
    16              * 3.Build a instance of this type(instance可以理解为一个实例,就相当于实例化一个对象)
    17              * 4.Call Method.Invoke method to invoke it with the instance in step 3.
    18              */
    19             //OK, 我们按照步骤一步一步来:
    20 
    21             //step 1. 你也可以用上一篇里的方式,直接去拿类型
    22             Assembly assembly = Assembly.LoadFrom("PersonMoudle.dll");
    23             var name = assembly.GetName();
    24             Console.WriteLine(name);
    25 
    26 
    27             //step 2. 这里偷个懒,我们其实知道自己写的PersonMoudle里,只有一种类型,就是Person类型,所以我们只找Person类型
    28             var types = assembly.GetTypes();//These're all types in PersonMoudle.dll
    29             var personType = types.FirstOrDefault(t => t.Name.Equals("Person"));//You need check personType 'if not null' then to use.
    30 
    31 
    32             //step 3. See, we build it already.
    33             
    34             var instance = assembly.CreateInstance(personType.FullName, false);
    35             
    36             //step 4(1), 我们来调用一个无参数的、void的方法(SayHi),这个应该是最简单的了
    37               //根据第一篇的代码,我们需要首先拿到Person这个type中,所有可能用到的方法(这里用BindingFlags过滤了一些,但是觉得这样的写法不好,有更好方法的朋友欢迎告知,多谢!)
    38             var personMethods = personType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(m => !m.Attributes.ToString().Contains("Special"));
    39             var methodSayHi = personMethods.FirstOrDefault(m => m.Name.Equals("SayHi"));//我们定位到SayHi方法
    40             Console.WriteLine("SayHi方法的执行结果:");
    41             methodSayHi.Invoke(instance, null);//使用invoke方法去call,可以看到SayHi方法Console.WriteLine的结果。
    42             Console.WriteLine("SayHi方法的执行结束================");
    43             Console.WriteLine(Environment.NewLine);
    44 
    45             //step 4(2), 再来调用一个有参数,void的方法(Speak)。
    46             Console.WriteLine("Speak方法执行结果:");
    47             var methodSpeak = personMethods.FirstOrDefault(m => m.Name.Equals("Speak"));
    48             methodSpeak.Invoke(instance, new[] {"This is the speak method invoked."});
    49             Console.WriteLine("Speak方法的执行结束================");
    50             Console.WriteLine(Environment.NewLine);
    51 
    52             //var a = new {words = "Come, let's fuck", telto = "BaoBao"};
    53 
    54             //step 4(3), so...多个参数呢?聪明的你一定想得到
    55             Console.WriteLine("TelSomeone方法,打电话给隔壁包小姐");
    56             var methodTelSomeone = personMethods.FirstOrDefault(m => m.Name.Equals("TelSomeone"));
    57             methodTelSomeone.Invoke(instance, new []{"Miss Bao","Could come to my house?"});//谁知道怎么打乱参数位置调用?
    58             //notice: new[]{}这样的写法会自动推断强类型,如果有类型不同的参数,请使用new object[]{}的写法。
    59             Console.WriteLine("呼叫包小姐结束,先不写了,我离开一会。。。");
    60             Console.WriteLine(Environment.NewLine);
    61 
    62             //step 4(4), 有返回值的,这段真是太水了,哈哈
    63             Console.WriteLine("GetMySex方法,拿返回值");
    64             var methodGetMySex = personMethods.FirstOrDefault(m => m.Name.Equals("GetMySex"));
    65             var resultGetMySex = methodGetMySex.Invoke(instance, null);
    66             Console.WriteLine("我的性别是:" + resultGetMySex);
    67             Console.WriteLine(Environment.NewLine);
    68             
    69             //but if……构造函数有参数的呢?
    70             //思路:在上面我们写了反射的步骤,说白了就是先找到类型,然后实例化(通过反射),然后调用方法。我们我们应该尝试在构建instance的时候传入构造函数参数。事实证明,我的猜想是对的。
    71             //PARAMS: string name, int age, float height, string sex
    72             var con = personType.GetConstructor(new[] { typeof(string), typeof(int), typeof(float), typeof(string) });//我们找到指定的构造函数
    73             var instanceWithParams = con.Invoke(new object[] { "Sirius", 24, 172, "我不是人妖" });//这里拿到这个构造函数的实例
    74             Console.WriteLine("GetMySex方法,拿返回值(使用指定构造函数)");
    75             var resultGetMySex1 = methodGetMySex.Invoke(instanceWithParams, null);
    76             Console.WriteLine("我的性别是:" + resultGetMySex1);
    77             Console.WriteLine(Environment.NewLine);
    78 
    79             //通过查看.NET FRAMEWORK已经开放的源码,我们看到Assembly.CreateInstance方法实际上是调用了Activator.CreateInstance方法。我们当然也可以通过直接调用这个激活器,用another way去实现这种实例化。当然,无参数的实例化也是可以这么做的,.NET源码(988行):
    80             //TODO:http://referencesource.microsoft.com/#mscorlib/system/reflection/assembly.cs,81336f4535acc832
    81             //写法2:
    82             var instanceNewWay = Activator.CreateInstance(personType, new object[] {"Sirius", 24, 172, "我不是人妖(new way)"});
    83             Console.WriteLine("GetMySex方法,拿返回值(使用指定构造函数)");
    84             var resultGetMySex2 = methodGetMySex.Invoke(instanceNewWay, null);
    85             Console.WriteLine("我的性别是:" + resultGetMySex2);
    86             Console.WriteLine(Environment.NewLine);
    87         }
    88     }
    89 }

    行了,低胸们,已然是2%的废话+98%的代码,各位,再会!

    很多年以后,我有个名字叫西毒……
  • 相关阅读:
    tensorFlow(二)线性回归
    tensorFlow(一)相关重要函数理解
    Java NIO学习笔记-通道&缓冲区
    Code Plus插件开发笔记
    Java NIO框架Netty demo
    前端React开发入门笔记
    Tomcat性能优化
    Spring Boot整合Dubbo框架demo
    Spring Boot入门实例
    简单的RPC原型与实现原理
  • 原文地址:https://www.cnblogs.com/xidu/p/4267346.html
Copyright © 2020-2023  润新知