[C#, Generics]IsSubclassOf zonder Type parameter

Pagina: 1
Acties:
  • 110 views sinds 30-01-2008
  • Reageer

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ik ben bezig met een project waar ik een aantal Generic classes heb. In een ander project wil ik deze classes gebruiken door middel van reflection. Nu heb ik echter een probleem met het gebruik van de IsSubclassOf methode van Type.

Ik heb bijvoorbeeld de volgende Types
C#:
1
2
3
4
public class Base<T>{}

public class SubA : Base<int>{}
public class SubB : Base<float>{}

Nu wil ik met reflection alle Subclasses van Base<?> opvragen. Ik dacht dan doe ik het volgende

C#:
1
2
3
4
5
6
7
Type[] types = assembly.GetTypes();
foreach( Type type in types )
{
    type.IsSubClassOf( typeof( Base ) );//Compiler error want geen type mee gegeven
    type.IsSubClassOf( typeof( Base<> ) );//Compiled wel maar geeft altijd false terug in dit geval
    type.IsSubClassOf( typeof( Base<?> ) );//Compiler error want ? mag natuurlijk niet
}

In java heb je geloof ik iets van een ? zodat je Type parameter onbekend is. Zoiets wil ik eigenlijk in C# ook voor elkaar krijgen. Ik maak verder in mijn code die gebruik maakt van de reflection geen gebruik van de Type parameter dus het is ook niet echt belangrijk om dat te weten.

Weet iemand mischien hoe ik toch op kan vragen of een een class een Subclass is van mijn generic type zonder daarbij op te moeten geven met welke Type parameter de sub class overerft?

[ Voor 3% gewijzigd door Woy op 13-06-2006 11:37 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Type heeft wel een member GetGenericTypeDefinition, die een Type object retourneert dat de algemene generic type voorstelt, misschien kun je daar wat mee?

(En waarom IsSubClassOf aanroepen op Type, daar heb je de is operator toch voor?)

.edit: Dit werkt bij mij (C++/cli weliswaar)
C++:
1
2
3
4
5
6
7
8
9
10
11
generic<class T> ref class Foo { };

int main()
{
    Foo<int> f;

    Type ^ fType = f.GetType();
    Type ^ gType = fType->GetGenericTypeDefinition();

    std::cout << gType->Equals(Foo::typeid) << std::endl;
}

Output: 1

Dat typeof niet werkt op een Base vind ik een beetje vreemd. Het werkt in C++ ook (zij het op een ietwat andere manier), en in de typeof operator docs van C# staat:
The typeof operator can also be used on open generic types
.edit2: hmm heb je niet zo heel veel aan, als je een class Bar subclassed van Foo<int> dan kun je GetGenericTypeDefinition al niet meer aanroepen. 't Is idd wat irritant, zo op het eerste gezegd lijkt het dat je die hele classtree moet uitpluizen

Maar klopt je design wel in dat opzicht? Je wil kijken of iets een Base is, is het dan niet logisch dat je een überbaseclass hebt waar Base<T> ook weer van afleidt?

[ Voor 90% gewijzigd door .oisyn op 13-06-2006 12:16 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Als je alleen wil weten of een object overerft van Base dan kun je dat volgens mij gewoon oplossen met het is keyword. Die herkent volgensmij automagisch de base klasse.

Nu met Land Rover Series 3 en Defender 90


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ik heb zeg maar een abstracte class met een Type parameter. Op zich werkt dat in de werkelijke applicatie gewoon allemaal goed en kan ik er mee doen wat ik wil.

Ik wil echter een analyse tooltje maken die autmatisch alle types laadt die van Base<T> afgeleid zijn. Er is inderdaad nog wel weer een class waar Base<T> vanaf geleid is maar er zijn nog meer classes die dat doen en die wil ik dus niet hebben.

Die GetGenericTypeDefinition had ik idd ook gevonden maar dan zou ik dus idd de hele tree door moeten lopen om te kijken of die ergens mee overeen komt.

De is operator is toch niet bedoelt om van een Type te kijken van welk type het is het is om te kijken van welk Type een Instance is. Op het moment dat ik wil weten of het een Sub-Class is heb ik nog helemaal geen Instance. Want de volgende Code geeft volgens mij True
C#:
1
2
Type type = typeof( int );
MessageBox.Show( type is Type );

[ Voor 9% gewijzigd door Woy op 13-06-2006 12:56 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Topicstarter
Ik heb het nou wel opgelost door een functie te schrijven die gewoon door de Tree heenloopt en telkens naar de GetGenericTypeDefinition kijkt.

Maar ik blijf het vreemd vinden waarom ik niet gewoon het volgende kan doen
C#:
1
2
3
4
5
6
7
class Base<T>{}
class SubA : Base<int>{}

SubA sub = new SubA();

//Hier komt dus een compiler error
bool test = sub is Base<>;

De typeof operator werkt idd wel gewoon op open generic types. Maar waarom kan ik met de is operator niet tegen open generic types controleren?

[ Voor 4% gewijzigd door Woy op 13-06-2006 13:42 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

.edit: spuit 11, je vorige post stond er nog niet :+

over dat is keyword, je hebt gelijk, ik had even gemist dat je gewoon een array van types had ipv dat je het type van een instance af had gehaald.

Maar goed, zelf zo'n functie schrijven is natuurlijk ook niet heel erg ingewikkeld :)
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool IsGenericSubClassOf(Type ^ type, Type ^ genericBase)
{
    while(type)
    {
        if (type->IsGenericType && type->GetGenericTypeDefinition()->Equals(genericBase))
            return true;

        type = type->BaseType;
    }

    return false;
}


generic<class T> ref class Foo { };
ref class Bar : public Foo<int> { };
ref class Baz { };

int main()
{
    std::cout << IsGenericSubClassOf(Bar::typeid, Foo::typeid) << std::endl;
    std::cout << IsGenericSubClassOf(Baz::typeid, Foo::typeid) << std::endl;
}
De typeof operator werkt idd wel gewoon op open generic types. Maar waarom kan ik met de is operator niet tegen open generic types controleren?
Dat had idd wel handig geweest ja :)

[ Voor 14% gewijzigd door .oisyn op 13-06-2006 14:07 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1