1 調用非泛型方法
通過反射創建一個對象,然後調用其方法的一般過程爲:
- 加載程序集,並獲取類型
- 通過類型,實例化一個類型對象(調用靜態方法則不必實例化)
- 根據名稱、方法簽名、可訪問性等約束,獲取要調用的方法
- 通過 Invoke 方法,傳入實際參數,進行調用。
案例:
public class ReflectionTest
{
// 無參構造函數
public ReflectionTest(){}
public void Show(string name, int id)
{
Console.WriteLine("調用了Show(string, int)");
}
// 私有方法
private void Show2()
{
Console.WriteLine("調用了私有Show2()");
}
}
//下面通過反射調用方法
var assembly = Assembly.Load("XX");//XX是ReflectionTest所在的程序集名稱
var type = assembly.GetType("XX.ReflectionTest");
object oReflTest = Activator.CreateInstance(type);//會調用(無參)構造函數
MethodInfo mi = type.GetMethod("Show", new Type[] { typeof(string), typeof(int) });
mi.Invoke(oReflTest, new object[] { "123", 123 });
//調用私有方法
MethodInfo mi = type.GetMethod("Show2", BindingFlags.NonPublic|BindingFlags.Instance);
mi.Invoke(oReflTest, null);
2 調用泛型類的泛型方法
對於泛型類的泛型方法,過程與非泛型類的非泛型方法是一樣的,只不過,泛型類的實例化方式不太一樣,泛型方法的調用也不太一樣。
由於未指定泛型類型實參(T)的泛型類型是一種 開放類型,開放類型是不允許進行實例化的,因此,需首先指定 T 的類型實參(例如 int, string 等實際類型),將其轉爲 封閉類型 後才能進行實例化。泛型方法也是類似,需指定類型實參才能傳遞匹配的實際參數,進行調用。
案例:
public class GenericClass<T>
{
public void Show<W, X>(T t, W w, X x)
{
Console.WriteLine($"t.type={t.GetType().Name},w.type={w.GetType().Name},x.type=x.GetType().Name}");
}
}
//通過反射調用
assembly = Assembly.Load("XX");//XX是GenericClass<T>所在的程序集名稱
Type typeOpen = assembly.GetType("XX.GenericClass`1");//注意泛型類型名稱
//通過MakeGenericType()方法創建泛型類型
Type typeClosed = typeOpen.MakeGenericType(new Type[] { typeof(int) });
object oGenRefl = Activator.CreateInstance(typeClosed);
MethodInfo mi = typeClosed.GetMethod("Show");//沒有重載時可以不指定方法參數類型
MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
mi2.Invoke(oGenRefl, new object[] { 12, "12", DateTime.Now });//注意泛型類型的匹配
//輸出結果如下:
t.type=Int32,w.type=String,x.type=DateTime