C#秘密武器之反射——基础篇
先來一段有用的反射代碼
namespace Calculator { public interface Iwel { String Print(); } } namespace Calculator { public class Arithmetic:Iwel { /// <summary> /// 沒有帶參數(shù)的構(gòu)造函數(shù) /// </summary> public Arithmetic() {} public Arithmetic(int num1, int num2) { _num1 = num1; _num2 = num2; } private int _num1; public int Num1 { get { return _num1; } set { _num1 = value; } } private int _num2; public int Num2 { get { return _num2; } set { _num2 = value; } } public String Add(int num1, int num2) { Console.WriteLine("{0}+{1}={2}", num1, num2, num1 + num2); return "Add(int num1,int num2)方法是一個(gè)公有的帶參數(shù)的方法"; } private string Add() { return "Add()方法是一個(gè)私有的不傳參數(shù)的方法"; } private void Subtration(int num1, int num2) { Console.WriteLine("{0}-{1}={2}+Subtration(int num1,int num2)" + "方法是一個(gè)私有的帶有參數(shù)的方法 ",num1,num2,num1-num2); } public static void Multiplication(int num1, int num2) { Console.WriteLine("{0}*{1}={2} Multiplication(int num1,int num2)"+"是一個(gè)公有的帶參數(shù)的靜態(tài)方法",num1,num2,num1+num2); } private static void Multiplication() { Console.WriteLine("Multiplication()是一個(gè)公有的帶參數(shù)的靜態(tài)方法"); } public String Writ() { return "Writ() 是一個(gè)公有的不帶參數(shù)的方法"; } #region Iwel 成員 public string Print() { return "歡迎您使用接口!"; } #endregion } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace BassLib { class Program { delegate void TestDelegate(int num1, int num2); static void Main(string[] args) { Assembly assembly = Assembly.Load("Calculator");//加載程序集 Console.WriteLine("得到Calculator.dll中的所有類"); Console.WriteLine("***********************************"); foreach (Type myType in assembly.GetTypes()) { //得到Calculator.dll中所有的類 Console.WriteLine(myType.Name + "是Calculator命中空間下的類"); } Console.WriteLine(" +++++++++++++++++++++++++++++++++++++"); Console.WriteLine("得到Calculator.dll中的模塊集"); Module[] modules = assembly.GetModules();//得到Calculator.dll中的模塊集合 foreach (Module module in modules) { Console.WriteLine(module.Name + "是Calculator中的一個(gè)模塊 "); } Console.WriteLine("*********************************************"); Console.WriteLine(""); Type type = typeof(Calculator.Arithmetic);//得到具體的類型 Console.WriteLine("具體的類型是" + type.Name); Console.WriteLine(" {0}是不是public類型:{1}", type, type.IsPublic); Console.WriteLine("{0}是不是private類型:{1}", type, type.IsNotPublic); Console.WriteLine("*********************************************"); Console.WriteLine(""); PropertyInfo[] memberInfo = type.GetProperties();//得到類中的屬性 foreach (PropertyInfo var in memberInfo) { Console.WriteLine(type + "類的屬性有" + var.Name); } Console.WriteLine("**********************************************"); Console.WriteLine(""); Type[] t = type.GetInterfaces();//得到接口 foreach (Type var in t) { Console.WriteLine(var.Name + "是Calculator.dll中的接口"); } Console.WriteLine("*****************************************"); Console.WriteLine(""); Console.WriteLine("方法的返回類型,方法傳參的類型"); //查找私有的方法 MethodInfo[] method = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (MemberInfo var in method) { Console.WriteLine("私有方法: 方法名 ={0} 方法的信息={1}", var.Name, var); } //查找公有方法 MethodInfo[] methodpublic = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo var in methodpublic) { Console.WriteLine("公有方法:方法名={0} 方法的信息={1}", var.Name, var); } //查找公有的靜態(tài)方法 MethodInfo[] mathodstatic = type.GetMethods(BindingFlags.Public | BindingFlags.Static); foreach (MethodInfo var in mathodstatic) { Console.WriteLine("公有靜態(tài)方法: 方法名={0} 方法的信息 ={1}", var.Name, var); } //查找私有靜態(tài)方法 MethodInfo[] methodprivartstatic = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static); foreach (MethodInfo var in methodprivartstatic) { Console.WriteLine("私有靜態(tài)方法: 方法名={0} 方法的信息={1}", var.Name, var); } Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++"); Console.WriteLine("這是一個(gè)構(gòu)造方法的形式 "); ConstructorInfo[] con = type.GetConstructors();//獲得構(gòu)造函數(shù)的形式 foreach (ConstructorInfo var in con) { Console.WriteLine(var); } Console.WriteLine("_________________________________"); object obj = Activator.CreateInstance(type, null);//創(chuàng)建了一個(gè)不帶參數(shù)的實(shí)例 //公有非靜態(tài)帶參數(shù)和返回參數(shù)的方法的調(diào)用它 MethodInfo men1 = type.GetMethod("Add"); Console.WriteLine("調(diào)用{0}方法 ", men1); object[] nums1 = { 5, 4 };//參數(shù) Console.WriteLine(men1.Invoke(obj, nums1)); Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); //私有的非靜態(tài)方法的調(diào)用 MethodInfo men2 = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic); Console.WriteLine(men2.Invoke(obj, null)); Console.WriteLine("**********************************"); //公有的靜態(tài)帶參數(shù)的方法的調(diào)用 MethodInfo men3 = type.GetMethod("Multiplication", BindingFlags.Public | BindingFlags.Static); object[] nums2 = { 5, 6 }; men3.Invoke(null, nums2); Console.WriteLine("*****************"); //私有的靜態(tài)的 MethodInfo men4 = type.GetMethod("Multiplication", BindingFlags.NonPublic | BindingFlags.Static); men4.Invoke(null, null); Console.WriteLine("************************"); //動(dòng)態(tài)創(chuàng)建一個(gè)委托 Console.WriteLine("動(dòng)態(tài)創(chuàng)建委托"); TestDelegate dele = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "Subtration"); dele(9, 3); } } } View Code反射的幾種基本類型
1、System.Reflection.Assembly類
???? 通過Assembly可以動(dòng)態(tài)加載程序集,并查看程序集的內(nèi)部信息,其中最常用的就是Load()這個(gè)方法。
???? Assembly assembly=Assembly.Load("MyAssembly");
???? 利用Assembly的object CreateInstance(string) 方法可以反射創(chuàng)建一個(gè)對(duì)象,參數(shù)0為類名。
2、System.Type類
???? Type是最常用到的類,通過Type可以得到一個(gè)類的內(nèi)部信息,也可以通過它反射創(chuàng)建一個(gè)對(duì)象。一般有三個(gè)常用的方法可得到Type對(duì)象。
利用typeof() 得到Type對(duì)象
Type type=typeof(Example);
利用System.Object.GetType() 得到Type對(duì)象
Example example=new Example();
Type type=example.GetType();
利用System.Type.GetType() 得到Type對(duì)象
Type type=Type.GetType("MyAssembly.Example",false,true);
注意參數(shù)0是類名,參數(shù)1表示若找不到對(duì)應(yīng)類時(shí)是否拋出異常,參數(shù)1表示類名是否區(qū)分大小寫
?? 例子:
?? 我們最常見的是利用反射與Activator結(jié)合來創(chuàng)建對(duì)象:
Assembly assembly= Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type);3、反射方法
??? 1.通過 System.Reflection.MethodInfo能查找到類里面的方法
??? 代碼:
Type type=typeof(Example); MethodInfo[] listMethodInfo=type.GetMethods(); foreach(MethodInfo methodInfo in listMethodInfo) Cosole.WriteLine("Method name is "+methodInfo.Name);??? 2.我們也能通過反射方法執(zhí)行類里面的方法
?? 代碼:
Assembly assembly= Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type); MethodInfo methodInfo=type.GetMethod("Hello World"); //根據(jù)方法名獲取MethodInfo對(duì)象 methodInfo.Invoke(obj,null); //參數(shù)1類型為object[],代表Hello World方法的對(duì)應(yīng)參數(shù),輸入值為null代表沒有參數(shù)4、反射屬性
?? 1.通過 System.Reflection.PropertyInfo 能查找到類里面的屬性
???? 常用的方法有GetValue(object,object[]) 獲取屬性值和 SetValue(object,object,object[]) 設(shè)置屬性值
?? 代碼:
Type type=typeof(Example); PropertyInfo[] listPropertyInfo=type.GetProperties(); foreach(PropertyInfo propertyInfo in listPropertyInfo) Cosole.WriteLine("Property name is "+ propertyInfo.Name);?? 2.我們也可以通過以下方法設(shè)置或者獲取一個(gè)對(duì)象的屬性值
?? 代碼:
Assembly assembly=Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type); PropertyInfo propertyInfo=obj.GetProperty("Name"); //獲取Name屬性對(duì)象 var name=propertyInfo.GetValue(obj,null); //獲取Name屬性的值 PropertyInfo propertyInfo2=obj.GetProperty("Age"); //獲取Age屬性對(duì)象 propertyInfo2.SetValue(obj,34,null); //把Age屬性設(shè)置為345、反射字段
??? 通過 System.Reflection.FieldInfo 能查找到類里面的字段
??? 它包括有兩個(gè)常用方法SetValue(object ,object )和GetValue(object)? 因?yàn)槭褂梅椒ㄅc反射屬性非常相似,在此不再多作介紹
6、反射特性
?? 通過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個(gè)類里面的特性,以下例子可以反射出一個(gè)類的所有特性
?? 代碼:
Type type=typeof("Example"); object[] typeAttributes=type.GetCustomAttributes(false); //獲取Example類的特性 foreach(object attribute in typeAttributes) Console.WriteLine("Attributes description is "+attribute.ToString());?? 通過下面例子,可以獲取Example類Name屬性的所有特性
?? 代碼:
public class Example{[DataMemberAttribute]publics string Name{get;set;}..................}Type type = typeof(Example); PropertyInfo propertyInfo=type.GetProperty("Name"); //獲取Example類的Name屬性foreach (object attribute in propertyInfo.GetCustomAttributes(false)) //遍歷Name屬性的所有特性Console.WriteLine(“Property attribute: "+attribute.ToString());7、反射成員
我們先考慮一下對(duì)于一個(gè)類型Type,可能會(huì)包含什么類型,常見的有字段、屬性、方法、構(gòu)造函數(shù)、接口、嵌套類型等。MemberInfo 類代表著 Type的成員類型,值得注意的是Type類本身又繼承自MemberInfo類,理解起來并不困難,因?yàn)橐粋€(gè)類型經(jīng)常也是另一類型的成員。Type類提供 GetMembers()、GetMember()、FindMember()等方法用于獲取某個(gè)成員類型。
我們?cè)偬砑右粋€(gè)方法 MemberExplore(),來查看一個(gè)類型的所有成員類型。
namespace Demo{ class SimpleExplore { static void Main(string[] args) { MemberExplore(typeof(DemoClass)); } ? public static void MemberExplore(Type t) { StringBuilder sb = new StringBuilder(); MemberInfo[] memberInfo = t.GetMembers(); sb.Append("查看類型 " + t.Name + "的成員信息:\n"); foreach (MemberInfo mi in memberInfo) { sb.Append("成員:" + mi.ToString().PadRight(40) + " 類型: " + mi.MemberType + "\n"); } Console.WriteLine(sb.ToString()); } } }
產(chǎn)生的輸出如下:
我們使用了GetMembers()方法獲取了成員信息的一個(gè)數(shù)組,然后遍歷了數(shù)組,打印了成員的名稱和類型。如同我們所知道的:Name屬性在編譯后成為了get_Name()和set_Name()兩個(gè)獨(dú)立的方法;myEvent事件的注冊(cè)(+=)和取消注冊(cè)(-=)分別成為了add_myEvent()和remove_myEvent方法。同時(shí),我們發(fā)現(xiàn)私有(private)字段name 沒有被打印出來,另外,基類System.Object的成員GetType()和Equals()也被打印了出來。
有的時(shí)候,我們可能不希望查看基類的成員,也可能希望查看私有的成員,此時(shí)可以使用GetMembers()的重載方法,傳入BindingFlags 位標(biāo)記參數(shù)來完成。BindingFlags位標(biāo)記對(duì)如何獲取成員的方式進(jìn)行控制(也可以控制如何創(chuàng)建對(duì)象實(shí)例,后面會(huì)說明)。對(duì)于本例,如果我們想獲取所有的公有、私有、靜態(tài)、實(shí)例成員,那么只需要這樣修改GetMembers()方法就可以了。
public static void MemberExplore(Type t) { StringBuilder sb = new StringBuilder(); //MemberInfo[] memberInfo = t.GetMembers(); MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); sb.Append("查看類型 " + t.Name + "的成員信息:\n"); foreach (MemberInfo mi in memberInfo) { sb.Append("成員:" + mi.ToString().PadRight(40) + " 類型: " + mi.MemberType + "\n"); } Console.WriteLine(sb.ToString()); }此時(shí)的輸出如下:
可以看到,繼承自基類 System.Object 的方法都被過濾掉了,同時(shí),打印出了私有的 name, myEvent 等字段。
現(xiàn)在如果我們想要獲取所有的方法(Method),那么我們可以使用 Type類的FindMembers()方法:
public static void MemberExplore(Type t) { StringBuilder sb = new StringBuilder(); ? //MemberInfo[] memberInfo = t.GetMembers(); ? //MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static // | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); ? MemberInfo[] memberInfo = t.FindMembers(MemberTypes.Method, // 說明查找的成員類型為 Method BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, "*"); ? sb.Append("查看類型 " + t.Name + "的成員信息:\n"); foreach (MemberInfo mi in memberInfo) { sb.Append("成員:" + mi.ToString().PadRight(40) + " 類型: " + mi.MemberType + "\n"); } Console.WriteLine(sb.ToString()); }Type.FilterName 返回一個(gè)MemberFilter類型的委托,它說明按照方法名稱進(jìn)行過濾,最后一個(gè)參數(shù)“*”,說明返回所有名稱(如果使用“Get*”,則會(huì)返回所有以Get開頭的方法)。
現(xiàn)在的輸出如下:
MemberInfo 類有兩個(gè)屬性值得注意,一個(gè)是DeclaringType,一個(gè)是 ReflectedType,返回的都是Type類型。DeclaredType 返回的是聲明該成員的類型。比如說,回顧我們之前的一段代碼:
MemberInfo[] members = typeof(DemoClass).GetMembers();
它將返回所有的公有成員,包括繼承自基類的Equals()等方法,對(duì)于Equals()方法來說,它的 DeclaringType 返回的是相當(dāng)于 typeof(Object) 的類型實(shí)例,因?yàn)樗窃?System.Object中被定義的;而它的ReflectedType 返回的則是相當(dāng)于 typeof(DemoClass) 類型實(shí)例,因?yàn)樗峭ㄟ^ DemoClass 的類型實(shí)例被獲取的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/WeiGe/p/4202626.html
總結(jié)
以上是生活随笔為你收集整理的C#秘密武器之反射——基础篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaweb项目tomcat检查不到当
- 下一篇: Java, C#, Swift语法对比速