基礎拾憶:
前言
MSDN定義:通過 System.Reflection 命名空間中的類以及 System.Type,您可以獲取有關已加載的程序集和在其中定義的類型(如類、接口和值類型)的信息。 您也可以使用反射在運行時創建類型實例,以及調用和訪問這些實例。
這句話可以看出反射的命名空間是System.Reflection和System.Type.主要功能是在已經加載的程序集里獲取接口、類、方法、字段、屬性、特性等類型信息,
1.反射優缺點
1.1.優點:
1、反射提高了程序的靈活性和擴展性。
2、降低耦合性,提高自適應能力。
3、它允許程序創建和控制任何類的對象,無需提前硬編碼目標類。
1.2.缺點:
1、性能問題:使用發射基本上是一種解釋操作,用於字段和方法接入時要遠慢於直接代碼。因此反射機制主要應用在對靈活性和拓展性要求很高的系統框架上,普通程序不建議使用。
2、使用反射會模糊程序內部邏輯;程序員希望在源代碼中看到程序的邏輯,反射卻繞過了源代碼的技術,因而會帶來維護的問題,反射代碼比相應的直接代碼更復雜。
層次結構
2.System.reflection命名空間
2.1包含的類如下:
Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及從此程序集中查找類型並創建該類型的實例。
Module 了解如下的類似信息:包含模塊的程序集以及模塊中的類等。您還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法。
ConstructorInfo 了解如下的類似信息:構造函數的名稱、參數、訪問修飾符(如 public 或 private)和實現詳細信息(如 abstract 或 virtual)等。
System.Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。
MethodInfo 來了解如下的類似信息:方法的名稱、返回類型、參數、訪問修飾符(如 public 或 private)和實現詳細信 息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法來調用特定的方法。
FieldInfo 來了解如下的類似信息:字段的名稱、訪問修飾符(如 public 或 private)和實現詳細信息(如 static)等;並獲取或設置字段值。
EventInfo 來了解如下的類似信息:事件的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等;並添加或移除事件處理程序。
PropertyInfo 來了解如下的類似信息:屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等;並獲取或設置屬性值。
ParameterInfo 來了解如下的類似信息:參數的名稱、數據類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。
3.命名空間System.Type
3.1.Type類的屬性:
Name 數據類型名
FullName 數據類型的完全限定名(包括命名空間名)
Namespace 定義數據類型的命名空間名
IsAbstract 指示該類型是否是抽象類型
IsArray 指示該類型是否是數組
IsClass 指示該類型是否是類
IsEnum 指示該類型是否是枚舉
IsInterface 指示該類型是否是接口
IsPublic 指示該類型是否是公有的
IsSealed 指示該類型是否是密封類
IsValueType 指示該類型是否是值類型
3.2 Type類的方法:
GetConstructor(), GetConstructors():返回ConstructorInfo類型,用於取得該類的構造函數的信息
GetEvent(), GetEvents():返回EventInfo類型,用於取得該類的事件的信息
GetField(), GetFields():返回FieldInfo類型,用於取得該類的字段(成員變量)的信息
GetInterface(), GetInterfaces():返回InterfaceInfo類型,用於取得該類實現的接口的信息
GetMember(), GetMembers():返回MemberInfo類型,用於取得該類的所有成員的信息
GetMethod(), GetMethods():返回MethodInfo類型,用於取得該類的方法的信息
GetProperty(), GetProperties():返回PropertyInfo類型,用於取得該類的屬性的信息 可以調用這些成員,其方式是調用Type的InvokeMember()方法,或者調用 MethodInfo, PropertyInfo和其他類的Invoke()方法。
4.具體用法
4.1、假設你要反射一個 DLL 中的類,並且沒有引用它(即未知的類型):
Assembly assembly = Assembly.LoadFile("程序集路徑,即物理路徑"); // 加載程序集(EXE 或 DLL) object obj = assembly.CreateInstance("類的完全限定名,即包括命名空間"); // 創建類的實例
4.2、若要反射當前項目中的類(即當前項目已經引用它了)可以為:
Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當前程序集 object obj = assembly.CreateInstance("類的完全限定名,即包括命名空間"); // 創建類的實例,返回為 object 類型,需要強制類型轉換
4.3、兩者結合:
Type type = Type.GetType("類的完全限定名"); object obj = type.Assembly.CreateInstance(type);
5.實例
5.1、創建對象實例
/// <summary> /// 反射幫助類 /// </summary> public static class ReflectionHelper { /// <summary> /// 創建對象實例 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fullName">命名空間.類型名</param> /// <param name="assemblyName">程序集</param> /// <returns></returns> public static T CreateInstance<T>(string fullName, string assemblyName) { string path = fullName + "." + assemblyName;//命名空間.類型名,程序集 Type o = Type.GetType(path);//加載類型 object obj = Activator.CreateInstance(o, true);//根據類型創建實例 return (T)obj;//類型轉換並返回 } /// <summary> /// 創建對象實例 /// </summary> /// <typeparam name="T">要創建對象的類型</typeparam> /// <param name="assemblyName">類型所在程序集名稱</param> /// <param name="nameSpace">類型所在命名空間</param> /// <param name="className">類型名</param> /// <returns></returns> public static T CreateInstance<T>(string assemblyName, string nameSpace, string className) { try { string fullName = nameSpace + "." + className;//命名空間.類型名 //此為第一種寫法 object ect = Assembly.Load(assemblyName).CreateInstance(fullName);//加載程序集,創建程序集里面的 命名空間.類型名 實例 return (T)ect;//類型轉換並返回 //下面是第二種寫法 //string path = fullName + "," + assemblyName;//命名空間.類型名,程序集 //Type o = Type.GetType(path);//加載類型 //object obj = Activator.CreateInstance(o, true);//根據類型創建實例 //return (T)obj;//類型轉換並返回 } catch { //發生異常,返回類型的默認值 return default(T); } } }
5.2、調用方法實例
public void reflectTest() { System.Reflection.Assembly ass; Type type; object obj; try { ass = System.Reflection.Assembly.LoadFile(@"d:\ReflectWyl.dll"); type = ass.GetType("WebTest.ReflectTest");//必須使用名稱空間+類名稱 System.Reflection.MethodInfo method = type.GetMethod("WriteString");//方法的名稱 obj = ass.CreateInstance("WebTest.ReflectTest");//必須使用名稱空間+類名稱 string s = (string)method.Invoke(obj, new string[] { "Wangyanling" }); //實例方法的調用 //靜態方法的調用 method = type.GetMethod("WriteName");//方法的名稱 s = (string)method.Invoke(null, new string[] { "Wangyanling" }); //無參數的實例方法 method = type.GetMethod("WriteNoPara"); s = (string)method.Invoke(obj, null); // Response.Write(s+"<br>"); method = null; } catch (Exception ex) { } finally { ass = null; type = null; obj = null; } }
5.3、對象轉換為Json
對象進行反序列化我們應該在項目中或多火燒都有遇到過,在這當中也是用到了反射不知道,您有沒有注意過。現在把對象轉為json的實現貼出來,大家根據代碼在了解一下反射。

/// <summary> /// 對象轉換為Json /// </summary> /// <param name="jsonObject">對象</param> /// <returns>Json字符串</returns> public static string ToJson(object jsonObject) { string jsonString = "{"; PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties(); for (int i = 0; i < propertyInfo.Length; i++) { object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null); string value = string.Empty; if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan) { value = "'" + objectValue.ToString() + "'"; } else if (objectValue is string) { value = "'" + ToJson(objectValue.ToString()) + "'"; } else if (objectValue is IEnumerable) { value = ToJson((IEnumerable)objectValue); } else { value = ToJson(objectValue.ToString()); } jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ","; } jsonString.Remove(jsonString.Length - 1, jsonString.Length); return jsonString + "}"; }
5.4、工廠模式
設計模式小提示:
簡單工廠:簡單實用,但違反開放封閉;
工廠方法:開放封閉,單一產品;
抽象工廠:開放封閉,多個產品;
反射工廠:可以最大限度的解耦。
下面一個例子就是用反射實現工廠模式
namespace FactoryPartern { public interface IFactoryOrg { IOrg CreateOrg(); } public class FactoryA : IFactoryOrg { public IOrg CreateVehicle() { return new A(); } } public class FactoryB : IFactoryOrg { public IOrg CreateVehicle() { return new B(); } } public interface IOrg { void go(); } public class A : IOrg { public void go() { // } } public class B : IOrg { public void go() { // } } class ReflectFactory { public static IOrg CreateOrgByReflect(string typeName) { string namespaceStr = "FactoryPartern"; string tempChar = "."; //注意使用Type.GetType(String classname)時,必須指定其命名空間,否則返回為null Type type = Type.GetType(namespaceStr + tempChar + typeName, true); ConstructorInfo ci = type.GetConstructor(System.Type.EmptyTypes); return (IOrg)ci.Invoke(null); } } }
進行調用
IOrg org= ReflectFactory.CreateOrgByReflect("A"); org.go();