前言

今天為了程式能寫好看一點,一直在糾結怎麼指定動態泛型,

但是想想實用性好像不太大,可是把這技術忘掉太可惜XD

還是記錄下來,以防忘記

以下程式範例

類別
  • cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// where 條件說明 
// class : 傳入一定要是參考型別
// new() : 該類別一定要有公開的建構式方法
public class DynamicGeneric<T> where T : class , new()
{
public string Name { get; set; }

public void SayHello()
{
Console.WriteLine("Hello");
}

public T GetInstance()
{
return new T();
}

}

public class MyClass1
{
public string MyProperty { get; set; }

public void MyMethod()
{
Console.WriteLine("I'm Class1 Method");
}
}

執行過程

執行過程
  • cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static void Main(string[] args)
{
// 動態指定泛型的方法
// 效果大概像這樣
// var type = typeof(MyClass1);
// DynamicGeneric<type> d = new DynamicGeneric<type>();
// 當然,上面這兩行是不能跑的,只是要表達將泛型用變數的方式傳入

// Step 1: 取得該類別Type
var genericListType = typeof(DynamicGeneric<>);
// Step 2: 指定泛型型別
var specificListType = genericListType.MakeGenericType(typeof(MyClass1));
// Step 3: 建立Instance
object instance = Activator.CreateInstance(specificListType);
/*------------------這樣就動態指定泛型完成了------------------*/

// 因為回傳的物件是object,除非轉型才能用強行別的方式操作
// 不然就得用反射方法(Reflection),來操作方法或屬性

Type instanceType = instance.GetType();

// 取得屬性值
string name = instanceType.InvokeMember(
"Name", // 屬性名稱
System.Reflection.BindingFlags.GetProperty, // 執行取得屬性
null,
instance,
null
) as string;

// 執行方法
instanceType.InvokeMember(
"SayHello",//方法名稱
BindingFlags.InvokeMethod, // 執行調用方法
null,
instance,
null
); // output : Hello

}

參考資料

stackoverflow dotblogs msdn