C#秘密武器之反射——基础篇
先來一段有用的反射代碼
namespace Calculator { public interface Iwel { String Print(); } } namespace Calculator { public class Arithmetic:Iwel { /// <summary> /// 沒有帶參數的構造函數 /// </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)方法是一個公有的帶參數的方法"; } private string Add() { return "Add()方法是一個私有的不傳參數的方法"; } private void Subtration(int num1, int num2) { Console.WriteLine("{0}-{1}={2}+Subtration(int num1,int num2)" + "方法是一個私有的帶有參數的方法 ",num1,num2,num1-num2); } public static void Multiplication(int num1, int num2) { Console.WriteLine("{0}*{1}={2} Multiplication(int num1,int num2)"+"是一個公有的帶參數的靜態(tài)方法",num1,num2,num1+num2); } private static void Multiplication() { Console.WriteLine("Multiplication()是一個公有的帶參數的靜態(tài)方法"); } public String Writ() { return "Writ() 是一個公有的不帶參數的方法"; } #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中的一個模塊 "); } 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("這是一個構造方法的形式 "); ConstructorInfo[] con = type.GetConstructors();//獲得構造函數的形式 foreach (ConstructorInfo var in con) { Console.WriteLine(var); } Console.WriteLine("_________________________________"); object obj = Activator.CreateInstance(type, null);//創(chuàng)建了一個不帶參數的實例 //公有非靜態(tài)帶參數和返回參數的方法的調用它 MethodInfo men1 = type.GetMethod("Add"); Console.WriteLine("調用{0}方法 ", men1); object[] nums1 = { 5, 4 };//參數 Console.WriteLine(men1.Invoke(obj, nums1)); Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); //私有的非靜態(tài)方法的調用 MethodInfo men2 = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic); Console.WriteLine(men2.Invoke(obj, null)); Console.WriteLine("**********************************"); //公有的靜態(tài)帶參數的方法的調用 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("************************"); //動態(tài)創(chuàng)建一個委托 Console.WriteLine("動態(tài)創(chuàng)建委托"); TestDelegate dele = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "Subtration"); dele(9, 3); } } } View Code反射的幾種基本類型
1、System.Reflection.Assembly類
???? 通過Assembly可以動態(tài)加載程序集,并查看程序集的內部信息,其中最常用的就是Load()這個方法。
???? Assembly assembly=Assembly.Load("MyAssembly");
???? 利用Assembly的object CreateInstance(string) 方法可以反射創(chuàng)建一個對象,參數0為類名。
2、System.Type類
???? Type是最常用到的類,通過Type可以得到一個類的內部信息,也可以通過它反射創(chuàng)建一個對象。一般有三個常用的方法可得到Type對象。
利用typeof() 得到Type對象
Type type=typeof(Example);
利用System.Object.GetType() 得到Type對象
Example example=new Example();
Type type=example.GetType();
利用System.Type.GetType() 得到Type對象
Type type=Type.GetType("MyAssembly.Example",false,true);
注意參數0是類名,參數1表示若找不到對應類時是否拋出異常,參數1表示類名是否區(qū)分大小寫
?? 例子:
?? 我們最常見的是利用反射與Activator結合來創(chuàng)建對象:
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"); //根據方法名獲取MethodInfo對象 methodInfo.Invoke(obj,null); //參數1類型為object[],代表Hello World方法的對應參數,輸入值為null代表沒有參數4、反射屬性
?? 1.通過 System.Reflection.PropertyInfo 能查找到類里面的屬性
???? 常用的方法有GetValue(object,object[]) 獲取屬性值和 SetValue(object,object,object[]) 設置屬性值
?? 代碼:
Type type=typeof(Example); PropertyInfo[] listPropertyInfo=type.GetProperties(); foreach(PropertyInfo propertyInfo in listPropertyInfo) Cosole.WriteLine("Property name is "+ propertyInfo.Name);?? 2.我們也可以通過以下方法設置或者獲取一個對象的屬性值
?? 代碼:
Assembly assembly=Assembly.Load("MyAssembly"); Type type=assembly.GetType("Example"); object obj=Activator.CreateInstance(type); PropertyInfo propertyInfo=obj.GetProperty("Name"); //獲取Name屬性對象 var name=propertyInfo.GetValue(obj,null); //獲取Name屬性的值 PropertyInfo propertyInfo2=obj.GetProperty("Age"); //獲取Age屬性對象 propertyInfo2.SetValue(obj,34,null); //把Age屬性設置為345、反射字段
??? 通過 System.Reflection.FieldInfo 能查找到類里面的字段
??? 它包括有兩個常用方法SetValue(object ,object )和GetValue(object)? 因為使用方法與反射屬性非常相似,在此不再多作介紹
6、反射特性
?? 通過System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一個類里面的特性,以下例子可以反射出一個類的所有特性
?? 代碼:
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、反射成員
我們先考慮一下對于一個類型Type,可能會包含什么類型,常見的有字段、屬性、方法、構造函數、接口、嵌套類型等。MemberInfo 類代表著 Type的成員類型,值得注意的是Type類本身又繼承自MemberInfo類,理解起來并不困難,因為一個類型經常也是另一類型的成員。Type類提供 GetMembers()、GetMember()、FindMember()等方法用于獲取某個成員類型。
我們再添加一個方法 MemberExplore(),來查看一個類型的所有成員類型。
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()); } } }
產生的輸出如下:
我們使用了GetMembers()方法獲取了成員信息的一個數組,然后遍歷了數組,打印了成員的名稱和類型。如同我們所知道的:Name屬性在編譯后成為了get_Name()和set_Name()兩個獨立的方法;myEvent事件的注冊(+=)和取消注冊(-=)分別成為了add_myEvent()和remove_myEvent方法。同時,我們發(fā)現私有(private)字段name 沒有被打印出來,另外,基類System.Object的成員GetType()和Equals()也被打印了出來。
有的時候,我們可能不希望查看基類的成員,也可能希望查看私有的成員,此時可以使用GetMembers()的重載方法,傳入BindingFlags 位標記參數來完成。BindingFlags位標記對如何獲取成員的方式進行控制(也可以控制如何創(chuàng)建對象實例,后面會說明)。對于本例,如果我們想獲取所有的公有、私有、靜態(tài)、實例成員,那么只需要這樣修改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()); }此時的輸出如下:
可以看到,繼承自基類 System.Object 的方法都被過濾掉了,同時,打印出了私有的 name, myEvent 等字段。
現在如果我們想要獲取所有的方法(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 返回一個MemberFilter類型的委托,它說明按照方法名稱進行過濾,最后一個參數“*”,說明返回所有名稱(如果使用“Get*”,則會返回所有以Get開頭的方法)。
現在的輸出如下:
MemberInfo 類有兩個屬性值得注意,一個是DeclaringType,一個是 ReflectedType,返回的都是Type類型。DeclaredType 返回的是聲明該成員的類型。比如說,回顧我們之前的一段代碼:
MemberInfo[] members = typeof(DemoClass).GetMembers();
它將返回所有的公有成員,包括繼承自基類的Equals()等方法,對于Equals()方法來說,它的 DeclaringType 返回的是相當于 typeof(Object) 的類型實例,因為它是在 System.Object中被定義的;而它的ReflectedType 返回的則是相當于 typeof(DemoClass) 類型實例,因為它是通過 DemoClass 的類型實例被獲取的。
?
轉載于:https://www.cnblogs.com/WeiGe/p/4202626.html
總結
以上是生活随笔為你收集整理的C#秘密武器之反射——基础篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javaweb项目tomcat检查不到当
- 下一篇: python画五子棋棋盘_python