2010-04-09 12 views
9

mam sposób jak następuje:C# Pass rodzajowych przy starcie

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

Potem stworzył klasę:

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

Chciałbym móc wywoływać

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

gdzie będzie używał typu THIS, aby przejść do HandleBase. Zasadniczo uzyskałoby to całą HandleBase, która ma właściciela tego typu.

Jak mogę to osiągnąć?

EDIT:

Używam .NET 2.0, tak rozwiązania większa niż 2,0 nie będą działać.

Chodzi o to, aby ControlBase miał kolekcję innych ControlBase dla "dzieci". Następnie mogą być zapytani na podstawie ich typu z GetControls<T>(). To pozwoliłoby mi na przykład uzyskać całą HandleBase dla kształtu. Wtedy mogę wziąć wszystkie te i ustawić Visible = false lub zrobić coś innego z nimi. W ten sposób mogę manipulować dziećmi określonego typu dla kolekcji.

HandleBase<TOwner> wymaga TOwnera, ponieważ ma odniesienie do "rodzaju posiadania". Możesz więc dodać tylko coś, co rozszerza HandleBase na kształt. Ma sens?

Dzięki za pomoc!

+2

@TheCloudlessSky, dlaczego wywołać 'this.GetType()'? jeśli wywołujesz 'GetControls >();' z klasy opartej na instancji [jak "this" wskazuje], dlaczego nie po prostu użyć deklarowanej nazwy typu klasy implementującej? jeśli jest to klasa podstawowa, istnieją sposoby ujawnienia typu podklasy klasie bazowej. –

+0

Patrz edycja powyżej. – TheCloudlessSky

Odpowiedz

0

ten jest specyficzny dla mojego wykonania tego, ale udało mi się rozwiązać ten problem poprzez stworzenie non-generic HandleBase a potem ogólny HandleBase<TOwner> ponieważ jedynym miejscu Właścicielem nieruchomości był TOwner.

Następnie, gdy mogę zadzwonić pod numer GetControls<HandleBase> i uzyskać wszystkie HandleBase bez względu na właściciela.

Dzięki wszystkim za odpowiedzi!

2

Nie możesz. Generics jest funkcją czasu kompilacji. Będziesz musiał podać typ jako nietypowy parametr metody i przekazać go tam.

+1

Możesz użyć odbicia, aby to zrobić. Ale to naprawdę wydaje się przesadą dla tego, co jest opisane w problemie. Zgadzam się, aby zamiast tego podać odniesienie do funkcji. –

+0

System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); Wpisz t = a.GetType ("SeaSharpWinApp8.Program"); MethodInfo mi = t.GetMethod ("f", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo miGeneric = mi.MakeGenericMethod (nowy typ [] {typof (ciąg)}); miGeneric.Invoke (null, nowy obiekt [] {"works"}); –

+0

To wywołanie MakeGenericMethod, które pozwala to zrobić. Najpierw musisz pobrać MethodInfo, a następnie uzyskać inny z konkretnymi typami, których chcesz użyć. Jeśli jest to typ ogólny, zamiast tego wywołujemy wywołanie MakeGeneric * na poziomie typu. –

13

Możesz to zrobić, określając typ podczas kompilacji lub używając refleksji.

Można zrobić to z refleksji tak:

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

Zauważ, że byłoby zwrócić object; nie można go przesłać do IEnumerable<T> (chyba że wiesz, co T jest w trakcie kompilacji, w takim przypadku nie ma sensu). Będziesz mógł przesłać go do IEnumerable.

Jest to jednak zły pomysł.
Prawdopodobnie istnieje lepsze rozwiązanie dla Ciebie; proszę podać więcej szczegółów.

+0

jest to możliwe za pomocą odbicia? ** Jak? ** – serhio

+3

Jest to możliwe przy użyciu odbicia, przez wywołanie 'typeof (SomeClass) .GetMethod (" GetControls ") .MagentGenericMethod (typeof (HandleBase <>) .MetGenericType (GetType())) Invoke (someObject, null) ' – SLaks

+0

Dlaczego zostało to odrzucone? – SLaks

1

Należy zauważyć, że parametry typu nie są zmiennymi. Dlatego nie można używać zmiennej zamiast parametru typu.

Można było jednak to zrobić poprzez odbicie, lub za pomocą specjalnego konstrukt, który jest dość ograniczony, ale może rozwiązać sprawę:

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

Prawdopodobnie nie ma sposobu, aby robić to, co prosić. Rozszerzając Twój przykład:

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

Jak powinien wyglądać typ X? Jednak z innych informacji w tle wydaje się, że trzeba uzyskać listę wszystkich kontroli danego typu.Można to zrobić na przykład w taki sposób:

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

zależności od innych zastosowań i celów można także chcą powrócić nierodzajową IEnumerable.

0

Od GetControls() zwraca wyliczenie, można znaleźć sposób, aby filtrować wynikowy wyliczenie z .OfType <T>, coś

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

Będziesz potrzebować rodzajowe ograniczenie somehwere wzdłuż linii

where T2 : T 
+0

To jest specyficzne dla> = 3.0, zapomniałem wspomnieć, że używam wersji 2.0. – TheCloudlessSky

Powiązane problemy