目錄
- 程式集載入
- 獲取型別資訊
- 構造型別例項
- 通過反射發現成員
- 呼叫成員
一、程式集載入
Load方法:CLR通過呼叫System.Rreflection.Assemblly類的靜態方法來顯示載入程式集。
public static Assembly Load(AssemblyName assemblyRef);
public static Assembly Load(string assemblyString);
LoadFrom方法:同樣我們可以使用 遠端載入程式集。此方法首先開啟程式集,並通過 public static AssemblyName GetAssemblyName(string assemblyFile);方法提取到程式集名稱,然後再會使用Load方法載入程式集。
public static Assembly LoadFrom(string path);
ReflectionOnlyLoad方法:載入程式集,只是獲取程式集的相關資訊。但CLR禁止此程式集中的程式碼執行。
public static Assembly ReflectionOnlyLoad(string assemblyString);
同樣也有ReflectionOnlyLoadFrom
public static Assembly ReflectionOnlyLoadFrom(string path);
二、獲取型別資訊
1、System.Type.GetType方法
public static Type GetType(string typeName);
字串必須執行的是全名,對於基元型別不能識別,識別CLR型別。
2、System.Type.ReflectionOnlyGetType
public static Type ReflectionOnlyGetType(string typeName, bool throwIfNotFound, bool ignoreCase);
只是顯示反射上下文內容,不能夠執行程式碼。
3、操作符typeof(),可以對型別進行晚期繫結並與早期繫結型別進行比對。
static Encryption(object o) { //早期繫結:o.GetTye() //晚期繫結typeof if (o.GetType() == typeof(Encryption)) { } }
三、構造型別例項
1、System.Activator.CreateInstance
public static object CreateInstance(Type type);
public static ObjectHandle CreateInstance(string assemblyName, string typeName);
上面的方法返回值有的是ObjectHandle型別,此型別允許將一個AppDomian中的物件傳送到另一個AppDomian而且不需要具體化哪個物件。如果需要具體化具體的型別就可以呼叫 Unwrap()方法。
2、System.Activator.CreateComInstanceFrom
public static ObjectHandle CreateComInstanceFrom(string assemblyName, string typeName);
程式集和型別都是字串直接指定,不過,程式集需要使用LoadFrom方法來載入得到程式集,並且提取名稱作為引數傳遞。當然對於返回值我們也需要呼叫Unwrap()進行具體化。
System.Reflection.Assembly assy= System.Reflection.Assembly.LoadFrom(""); System.Activator.CreateComInstanceFrom(assy.FullName, "Encryption");
四、通過反射發現成員
層次結構
因為Reflection.MemberInfo是成員結構層次的根,所以需要了解一下MemberInfo的成員組成:
1、執行以下程式碼,區分一下DeclaringType和ReflectedType:
DeclaringType:宣告方法的類;ReflectedType:當前的反射類
public class UnitTest1 { [TestMethod] public void TestMethod1() { System.Reflection.MemberInfo[] mi = typeof(MyType).GetMembers(); foreach (var m in mi) { var dt= m.DeclaringType; var rt = m.ReflectedType; } } } public sealed class MyType { public override string ToString() { return null; } }
ToSting()方法,因為宣告它的類和當前所在的反射類是同一個即MyType。
Equal()方法,因為宣告它的類是Object,但是當前反射類是MyType。
以上就是DeclaringType和ReflectedType的區別。
2、BindingFlags:篩選返回的成員種類
我們可以呼叫Type的 GetMethod、GetProperty、GetNestedType各種Get。我們可以組合BindingFlags,來篩選我們需要的東西。
五、呼叫成員的型別
我們可以找出我們需要的東東,然後我們可以進行呼叫。呼叫屬性、方法、建構函式等等。
呼叫FieldInfo,可以獲取或者設定欄位的值;
呼叫ConstructorInfo,可以向構造傳遞實參,從而構造型別的一個例項;
呼叫MethodInfo,可以通過傳遞實參來呼叫方法,並返回它的返回值;
呼叫PropertyInfo,可以呼叫屬性的get和set訪問其方法。
1、呼叫方法
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, CultureInfo culture);
呼叫此方法可以在成員型別裡搜尋一個匹配的型別成員,如果沒找到,丟擲異常。如果找到,就會呼叫此成員。我們可以歸納以上行為為兩個階段:繫結和呼叫。
我們呼叫一個繫結器方法時,首先我們傳遞 目標成員 name、方法的所有引數型別 args 、指定的 BindingFlags invokeAttr 。
引數 name :目標成員。名字
引數 invokeAttr :這些位標識的組合可以幫助我們更好的定位我們的成員 IgnoreCase = 1, DeclaredOnly = 2,Instance = 4,Static = 8,Public = 16等
引數 binder :它的型別從System.Relflection.Binder 抽象型別派生的,從Binder派生的型別,封裝了InverMember方法確定繫結型別的規則。編譯器為我們定義了System.DefaultBinder 的實際型別可以為我們使用。可以幫助我們自動的型別轉換。
引數 target : 目標成員所在類的例項的一個引用。靜態類 =null。
引數 args: 傳遞的引數。
引數 culture: 如果有自己的繫結器可以使用此引數,如果前面引數使用了System.DefaultBinder,culture引數就可以省略了。
2、一次繫結,多次呼叫
我們利用Type的InvokeMember方法可以,訪問任何成員。但是如果多次呼叫,我們就需要多次進行繫結並呼叫,比較損耗效能。我們可以使用: