2010-04-09 70 views
9

我有類似下面的方法:C#通行證泛型在運行時

public IEnumerable<T> GetControls<T>() 
: where T : ControlBase 
{ 
// removed. 
} 

然後,我創建了一個類:

public class HandleBase<TOwner> : ControlBase 
: TOwner 
{ 
// Removed 
} 

我希望能夠調用

GetControls<HandleBase<this.GetType()>>; 

它將使用該類的類型傳遞給HandleBase。這基本上會得到所有擁有這種類型的HandleBase。

我該如何做到這一點?

編輯:

我使用.NET 2.0解決方案,所以大於2.0將無法正常工作。

這個想法是讓ControlBase擁有其他ControlBase for「children」的集合。然後他們可以根據他們的類型與GetControls<T>()查詢。例如,這可以讓我得到一個Shape的所有HandleBase。然後,我可以採取所有這些,並設置Visible = false或與他們一起做其他事情。因此,我可以操縱特定類型的兒童進行收藏。

HandleBase<TOwner>需要陶納,因爲它具有與「擁有類型」的引用。所以你只能添加任何將HandleBase擴展到Shape的東西。合理?

感謝您的幫助!

+2

@TheCloudlessSky,爲什麼調用'this.GetType()'?如果你正在調用'GetControls >();'從一個基於實例的類[如'this'指示],爲什麼不簡單地使用實現類的聲明類型名?如果這是一個基類,則有將子類的類型暴露給基類的方法。 – 2010-04-09 14:46:33

+0

請參閱上面的修改。 – TheCloudlessSky 2010-04-09 16:07:41

回答

0

這是具體到我實現這一點,但我可以通過創建一個非通用HandleBase,然後再一個通用HandleBase<TOwner>,因爲唯一的地方來解決這個TOWNER正在使用的是業主。

然後,當我可以調用GetControls<HandleBase>並獲得所有的HandleBase而不管所有者。

謝謝你的回答!

2

你不能。泛型是一個編譯時功能。您需要將該類型作爲非泛型參數包含在該方法中,並將其傳遞給該方法。

+1

你可以使用反射來做到這一點。但是對於問題中所描述的內容來說,這看起來真是太過於誇張了。我同意將類型引用傳遞給函數。 – 2010-04-09 14:31:44

+0

System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); 類型t = a.GetType(「SeaSharpWinApp8.Program」); MethodInfo mi = t.GetMethod(「f」,BindingFlags.Static | BindingFlags.NonPublic); MethodInfo miGeneric = mi.MakeGenericMethod(new Type [] {typeof(string)}); miGeneric.Invoke(null,new object [] {「works」}); – 2010-04-09 14:47:44

+0

這是MakeGenericMethod調用,可以讓你做到這一點。您必須先獲取MethodInfo,然後再獲取您想要使用的特定類型。如果它是一個泛型類型,那麼你在類型級別進行MakeGeneric *調用。 – 2010-04-09 14:48:42

13

您可以通過在編譯時指定類型或使用反射來執行此操作。

你可以用反射像這樣做:

typeof(SomeClass).GetMethod("GetControls") 
    .MakeGenericMethod(typeof(HandleBase<>).MakeGenericType(GetType())) 
    .Invoke(someObject, null); 

注意,它會返回一個object;你將無法將其轉換爲IEnumerable<T>(除非你知道編譯時T是什麼,在這種情況下沒有意義)。你可以將它投射到IEnumerable

但是,這是一個壞主意。
您可能有更好的解決方案;請提供更多細節。

+0

建議傳遞類型信息,這可以使用反射嗎? **如何?** – serhio 2010-04-09 14:31:03

+3

通過調用'typeof(SomeClass).GetMethod(「GetControls」)可以使用反射。MakeGenericMethod(typeof(HandleBase <>)。MakeGenericType(GetType()))。Invoke(someObject,null )' – SLaks 2010-04-09 14:33:06

+0

爲什麼這是低調? – SLaks 2010-04-09 14:37:09

1

請注意,類型參數不是變量。因此,您不能使用變量來代替類型參數。

你可以,但是,做到這一點通過反射,或通過使用特殊結構,這是非常有限的,但可以解決您的情況:

public class MyClass<TSelf> where TSelf: MyClass<TSelf> { 
    public IEnumerable<T> GetControls<T>() where T: ControlBase { 
    // removed. 
    } 

    public void MyCall() { 
     GetControls<HandleBase<TSelf>>(); 
    } 
} 

public class MyConcreteClass: MyClass<MyConcreteClass> { 
} 
0

有可能是沒有辦法的事,你問什麼。擴展你的例子:

X x = GetControls<HandleBase<this.GetType()>>; 

什麼樣的X應該在這裏?但是從其他背景信息看來,您需要獲取給定類型的所有控件的列表。你可以在這樣的方式,例如做到這一點:

public IEnumerable<ControlBase> GetControls(Type type) { 
//your logic here 
} 

根據您的其他用途,你可能也想返回非通用IEnumerable的目標。

0

的GetControls以來()返回一個枚舉,你可能會找到一個方法來生成的枚舉與.OfType <牛逼>,像

List<T2> list = controlList.GetControls<T>().OfType<T2>().ToList(); 

過濾您將需要一個通用的限制somehwere沿

where T2 : T 
+0

特定於> = 3.0,我忘記提及我正在使用2.0。 – TheCloudlessSky 2010-04-09 16:08:54