获取Type类型的构造函数
前言
有了前面的 C#反射 入门学习 01的知识,学习这篇估计是搓搓有余,它教会了我们获取方法的相关信息的两种形式与
使用反射调用方法, 如果你不会就去看前面的C#反射 入门学习 01 吧!
在前面的示例中,由于MyClass类型的对象是显示创建的,这样让我们想到了反射技术调用MyClass没有任何优势---
比普通方式复杂得多。但是如果运行时对象是动态的创建的,反射功能的优势就会显示出来。不做过多讲解,代码注释
够详细了,有了前面的知识你一定懂的!
注意:我们继续用前面的 MyClass类,但这里我们把它变成MyClassTwo,因为这里的MyClassTwo与前面的
MyClass稍有修改!
为了方便以后复习,这里折叠了MyClassTwo类
1 class MyClassTwo 2 { 3 int x; 4 int y; 5 public MyClassTwo(int i) 6 { 7 Console.WriteLine("Constructing MyClassTwo(int)"); 8 this.x=this.y = i; 9 } 10 public MyClassTwo(int i, int j) 11 { 12 Console.WriteLine("Constructing MyClassTwo(int , int)"); 13 this.x = i; 14 this.y = j; 15 Show(); 16 } 17 public int Sum() 18 { 19 return x + y; 20 } 21 public bool IsBetween(int i) 22 { 23 if (x < i && i < y) 24 { 25 return true; 26 } 27 return false; 28 } 29 public void Set(int a, int b) 30 { 31 Console.WriteLine("Inside Set(int,int)"); 32 x = a; 33 y = b; 34 Show(); 35 } 36 public void Set(double a, double b) 37 { 38 Console.WriteLine("Inside Set(double,double)"); 39 x = (int)a; 40 y = (int)b; 41 Show(); 42 } 43 public void Show() 44 { 45 Console.WriteLine("valus are x: " + x + " y: " + y); 46 } 47 }
应用程序代码
1 #region 获取Tyoe对象的构造函数 2 3 Type t = typeof(MyClassTwo); 4 int val; 5 //获得构造函数的信息 6 ConstructorInfo[] ci = t.GetConstructors(); 7 Console.WriteLine("可用的构造函数");//available constructors 8 foreach (ConstructorInfo c in ci) 9 { 10 Console.Write(" "+t.Name+ " ("); 11 //显示构造函数 12 ParameterInfo[] pi = c.GetParameters(); 13 for (int i = 0; i < pi.Length; i++) 14 { 15 Console.Write(" " + pi[i].ParameterType.Name + " " + pi[i].Name);//获得调用构造函数里成员的类型 16 if (i+1<pi.Length) 17 { 18 Console.Write(","); 19 } 20 } 21 Console.WriteLine(")"); 22 } 23 Console.WriteLine(); 24 25 //找到匹配的构造函数 26 int x; 27 for (x = 0; x < ci.Length; x++) 28 { 29 ParameterInfo[] pi = ci[x].GetParameters(); 30 if (pi.Length==2)//查找有两个参数的构造函数 31 { 32 break; 33 } 34 } 35 if (x == ci.Length) 36 { 37 Console.WriteLine("No matching constructor found"); 38 return; 39 } 40 else { Console.WriteLine("Two-parameter constructor found"); } 41 42 //如果找到带两个参数的构造函数,那么下面的语句实例化一个该类型的对象 43 object[] consargs = new object[2]; 44 consargs[0] = 10; 45 consargs[1] = 20; 46 object reflectOb = ci[x].Invoke(consargs); //传给构造函数,并执行reflectOb【MyClassTwo】实例上的方法 47 48 Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 49 Console.WriteLine("\nInvoking methods on reflectOb."); 50 Console.WriteLine(); 51 MethodInfo[] mi = t.GetMethods(); 52 53 // 调用每个方法 54 foreach (MethodInfo m in mi) 55 { 56 // 得到的参数 57 ParameterInfo[] pi = m.GetParameters(); 58 59 if (m.Name.Equals("Set", StringComparison.Ordinal) && 60 pi[0].ParameterType == typeof(int))//比较参数的Type类型 61 { 62 // This is Set(int, int). 63 object[] obj = new object[2]; 64 obj[0] = 9; 65 obj[1] = 18; 66 m.Invoke(reflectOb, obj); 67 } 68 else if (m.Name.Equals("Set", StringComparison.Ordinal) && 69 pi[0].ParameterType == typeof(double)) 70 { 71 // This is Set(double, double). 72 object[] obj = new object[2]; 73 obj[0] = 1.12; 74 obj[1] = 23.4; 75 m.Invoke(reflectOb, obj); 76 } 77 else if (m.Name.Equals("Sum", StringComparison.Ordinal)) 78 { 79 val = (int)m.Invoke(reflectOb, null); 80 Console.WriteLine("Sum is " + val); 81 } 82 else if (m.Name.Equals("IsBetween", StringComparison.Ordinal)) 83 { 84 object[] obj = new object[1]; 85 obj[0] = 14; 86 if ((bool)m.Invoke(reflectOb, obj)) 87 Console.WriteLine("14 is between x and y"); 88 } 89 else if (m.Name.Equals("Show")) 90 { 91 m.Invoke(reflectOb, null); 92 } 93 94 } 95 //构造函数 96 97 98 #endregion
从程序集获得类型
获得程序集的信息,前提是我们要编辑一个程序集供我们来获取,编辑程序集的代码折叠放下面:
1 class Demo 2 { 3 static void Main(string[] args) 4 { 5 Console.WriteLine("This is a placeholder."); //占位符 6 } 7 } 8 9 10 class MyClass 11 { 12 int x; 13 int y; 14 15 public MyClass(int i) 16 { 17 Console.WriteLine("Constructing MyClass(int). "); 18 x = y = i; 19 Show(); 20 } 21 22 public MyClass(int i, int j) 23 { 24 Console.WriteLine("Constructing MyClass(int, int). "); 25 x = i; 26 y = j; 27 Show(); 28 } 29 30 public int Sum() 31 { 32 return x + y; 33 } 34 35 public bool IsBetween(int i) 36 { 37 if ((x < i) && (i < y)) return true; 38 else return false; 39 } 40 41 public void Set(int a, int b) 42 { 43 Console.Write("Inside Set(int, int). "); 44 x = a; 45 y = b; 46 Show(); 47 } 48 49 // Overload Set. 50 public void Set(double a, double b) 51 { 52 Console.Write("Inside Set(double, double). "); 53 x = (int)a; 54 y = (int)b; 55 Show(); 56 } 57 58 public void Show() 59 { 60 Console.WriteLine("Values are x: {0}, y: {1}", x, y); 61 } 62 } 63 64 65 66 67 68 class AnotherClass 69 { 70 string msg; 71 72 public AnotherClass(string str) 73 { 74 msg = str; 75 } 76 77 public void Show() 78 { 79 Console.WriteLine(msg); 80 } 81 }
获得程序集的相关信息,首先要创建一个 Assembly对象,它没有定义公有的构造函数,它的对象实例是通过调用类的方法获得的。
这里使用LoadFrom()方法可以加载由文件名指定的程序集,格式:static Assembly LoadFrom(string ~.exe) ~.exe—>程序集文件名
一旦获得了Assembly 类型对象,就可以通过在该对象上调用GetType()方法得到它所定义的类型。格式:Type [] GetType() 它包含了
程序集中的类型,返回值是一个数组!
下面我们就来获得 .exe 里面的信息:
1 #region 从程序集获得类型 2 3 // 找到一个程序集,确定类型,并创建一个对象使用反射。 4 int val; 5 6 // Load the MyClasses.exe assembly. 加载MyClasses.exe程序集。 7 Assembly asm = Assembly.LoadFrom("MyClasses.exe"); 8 9 // Discover what types MyClasses.exe contains. 展现MyClasses.exe的类型 10 Type[] alltypes = asm.GetTypes(); 11 foreach (Type temp in alltypes) 12 Console.WriteLine("Found: " + temp.Name); 13 14 15 Console.WriteLine(); 16 17 // MyClass在这种情况下,使用第一个类 18 Type t = alltypes[0]; // use first class found 19 //后面的技术跟前面 《获取Type对象的构造函数本质一样》 20 Console.WriteLine("Using: " + t.Name); 21 22 // 获得构造函数的信息。 23 ConstructorInfo[] ci = t.GetConstructors(); 24 25 Console.WriteLine("Available constructors: "); 26 foreach (ConstructorInfo c in ci) 27 { 28 // 显示返回类型和名称 29 Console.Write(" " + t.Name + "("); 30 31 // 显示参数 32 ParameterInfo[] pi = c.GetParameters(); 33 34 for (int i = 0; i < pi.Length; i++) 35 { 36 Console.Write(pi[i].ParameterType.Name + 37 " " + pi[i].Name); 38 if (i + 1 < pi.Length) Console.Write(", "); 39 } 40 41 Console.WriteLine(")"); 42 } 43 Console.WriteLine(); 44 45 // 找到匹配的构造函数。 46 int x; 47 48 for (x = 0; x < ci.Length; x++) 49 { 50 ParameterInfo[] pi = ci[x].GetParameters(); 51 if (pi.Length == 2) break; 52 } 53 54 if (x == ci.Length) 55 { 56 Console.WriteLine("No matching constructor found."); 57 return; 58 } 59 else 60 Console.WriteLine("Two-parameter constructor found.\n"); 61 62 // 构造对象 63 object[] consargs = new object[2]; 64 consargs[0] = 10; 65 consargs[1] = 20; 66 object reflectOb = ci[x].Invoke(consargs); 67 68 Console.WriteLine("\nInvoking methods on reflectOb."); 69 Console.WriteLine(); 70 MethodInfo[] mi = t.GetMethods(); 71 72 // 调用每一个方法。 73 foreach (MethodInfo m in mi) 74 { 75 // 得到的参数 76 ParameterInfo[] pi = m.GetParameters(); 77 78 if (m.Name.Equals("Set", StringComparison.Ordinal) && 79 pi[0].ParameterType == typeof(int)) 80 { 81 // This is Set(int, int). 82 object[] obj = new object[2]; 83 obj[0] = 9; 84 obj[1] = 18; 85 m.Invoke(reflectOb, args); 86 } 87 else if (m.Name.Equals("Set", StringComparison.Ordinal) && 88 pi[0].ParameterType == typeof(double)) 89 { 90 // This is Set(double, double). 91 object[] obj = new object[2]; 92 obj[0] = 1.12; 93 obj[1] = 23.4; 94 m.Invoke(reflectOb, args); 95 } 96 else if (m.Name.Equals("Sum", StringComparison.Ordinal)) 97 { 98 val = (int)m.Invoke(reflectOb, null); 99 Console.WriteLine("sum is " + val); 100 } 101 else if (m.Name.Equals("IsBetween", StringComparison.Ordinal)) 102 { 103 object[] obj = new object[1]; 104 obj[0] = 14; 105 if ((bool)m.Invoke(reflectOb, args)) 106 Console.WriteLine("14 is between x and y"); 107 } 108 else if (m.Name.Equals("Show", StringComparison.Ordinal)) 109 { 110 m.Invoke(reflectOb, null); 111 } 112 } 113 114 115 #endregion
说明一点,其实 .dll 文件也是可以的 格式 :Assembly asm = Assembly.LoadFrom("MyClasses.dll");
全自动类型查询
前面是我们必须预先知道程序集里类的方法名称,那我们可不可以不必预先知道它的任何信息,同样能调用所需的全部信息?
答案是肯定的,此方法对于可视化设置工具很有用,因为它可以利用系统上所有可用的类型。
程序集还是上面的 MyClasses.exe 直接上应用程序代码。。。
1 #region 全自动化类型查询【没有假设任何先验知识情况下,利用MyClass】 2 3 int val; 4 Assembly asm = Assembly.LoadFrom("MyClasses.exe"); 5 6 Type[] alltypes = asm.GetTypes(); 7 8 Type t = alltypes[0]; // use first class found ***这里只查看了Demo类哦,别的可以自己去推敲下 9 10 Console.WriteLine("Using: " + t.Name); 11 12 ConstructorInfo[] ci = t.GetConstructors();//获得构造函数 13 14 // Use first constructor found. 15 ParameterInfo[] cpi = ci[0].GetParameters(); 16 object reflectOb; 17 18 if (cpi.Length > 0) 19 { 20 object[] consargs = new object[cpi.Length]; 21 22 // Initialize args. 23 for (int n = 0; n < cpi.Length; n++) 24 consargs[n] = 10 + n * 20; 25 26 // Construct the object. 27 reflectOb = ci[0].Invoke(consargs); 28 } 29 else 30 reflectOb = ci[0].Invoke(null); 31 32 33 Console.WriteLine("\nInvoking methods on reflectOb."); 34 Console.WriteLine(); 35 36 // Ignore inherited methods. 37 MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly | 38 BindingFlags.Instance | 39 BindingFlags.Public); 40 41 // Invoke each method. 42 foreach (MethodInfo m in mi) 43 { 44 Console.WriteLine("Calling {0} ", m.Name); 45 46 // Get the parameters. 47 ParameterInfo[] pi = m.GetParameters(); 48 49 // Execute methods. 50 switch (pi.Length) 51 { 52 case 0: // no args 53 if (m.ReturnType == typeof(int)) 54 { 55 val = (int)m.Invoke(reflectOb, null); 56 Console.WriteLine("Result is " + val); 57 } 58 else if (m.ReturnType == typeof(void)) 59 { 60 m.Invoke(reflectOb, null); 61 } 62 break; 63 case 1: // one arg 64 if (pi[0].ParameterType == typeof(int)) 65 { 66 object[] obj = new object[1]; 67 obj[0] = 14; 68 if ((bool)m.Invoke(reflectOb, obj)) 69 Console.WriteLine("14 is between x and y"); 70 else 71 Console.WriteLine("14 is not between x and y"); 72 } 73 break; 74 case 2: // two args 75 if ((pi[0].ParameterType == typeof(int)) && 76 (pi[1].ParameterType == typeof(int))) 77 { 78 object[] obj = new object[2]; 79 obj[0] = 9; 80 obj[1] = 18; 81 m.Invoke(reflectOb, obj); 82 } 83 else if ((pi[0].ParameterType == typeof(double)) && 84 (pi[1].ParameterType == typeof(double))) 85 { 86 object[] obj = new object[2]; 87 obj[0] = 1.12; 88 obj[1] = 23.4; 89 m.Invoke(reflectOb, obj); 90 } 91 break; 92 } 93 Console.WriteLine(); 94 } 95 96 #endregion
反射暂时学到这里, 做为一个入门者,估计需求供用了!
原文:http://www.cnblogs.com/izhiniao/p/3666382.html