2012-11-22 46 views
4

是否有可能實例在運行時的模板類例如實例化模板類:你能在運行時使用C#

Type type = Type.GetType("iTry.Workflow.Person"); 
WorkflowPropertyViewModel<type> propViewModel = new WorkflowPropertyViewModel<type>(); 

這顯然是行不通的。有其他方法可以做到嗎?

泛型類如下所示:

public class WorkflowPropertyViewModel<T> : IProperty<T> 
{ 
    public Task<T> ValueAsync 
    { 
     get; 
     set; 
    } 

    public T Value 
    { 
     get; 
     set; 
    } 

    public IQueryable<T> PossibleItems 
    { 
     get; 
     set; 
    } 
} 

回答

2

是的,你可以實例化一個泛型類,只有在運行時已知的類型,如:

public class A { } 
public class U<T> { 
    public T X { get; set; } 
} 

static void Main(string[] args) { 
    Type a = typeof(A); 
    Type u = typeof(U<>); 
    dynamic uOfA = Activator.CreateInstance(u.MakeGenericType(a)); 
    uOfA.X = new A(); 
    Console.WriteLine(uOfA.GetType()); 
    Console.WriteLine(uOfA.X.GetType()); 
} 

然而,這段代碼使用反射和動態類型,這兩者都可能導致大量的維修問題,所以你會更好地使用它們,或者尋找更簡單的解決方案。

+0

感謝這爲我工作。動態是似乎完成工作的東西。 – Bracher

6

您可以創建一個給定類型對象的任何類型的對象:

object o = Activator.CreateInstance(type); 

這是假設的類型有一個默認的構造函數。有傳遞構造函數參數的其他激活方法:

http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

爲了得到一個特定的泛型類型,你可以撥打MakeGenericType你的泛型類型定義

http://msdn.microsoft.com/en-us/library/system.type.makegenerictype.aspx

所以把它乾脆就看起來像這樣:

var type = Type.GetType("iTry.Workflow.Person"); 
var genericType = typeof(WorkflowPropertyViewModel<>).MakeGenericType(type); 
var o = Activator.CreateInstance(genericType); 
+2

有趣的問題是:如何獲得'type'?你應該回答這個樣本。 –

+0

以及如何在運行時爲模板提供類型 – tillerstarr

+0

@tillerstarr:這就是MakeGenericType的用途。順便說一句:它是「通用」而不是「模板」。 –

2

試試這個:

object o = Activator.CreateInstance(typeof(WorkflowPropertyViewModel<>).MakeGenericType(new Type[] {type})); 

注意,在代碼中你不能輕易引用類型,除非它實現了另一個非通用接口 - 所以你必須使用對象,而不是,或使用更多的反思。