标签:
在上一篇里,我们叨逼了好多如何获取到程序集里的对象,但是对象有了,还不知道怎么调,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 }
然后,我们在另一个项目里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%的代码,各位,再会!
C#中反射的使用(How to use reflect in CSharp)(2)
标签:
原文地址:http://www.cnblogs.com/xidu/p/4267346.html