2010-12-30 8 views
6

Angenommen, dass ich ein Objekt habe, wie könnte ich dann wissen, ob das Objekt von einer bestimmten generischen Klasse abgeleitet ist. Zum Beispiel:Wie kann ich wissen, ob ein Objekt von einer bestimmten generischen Klasse abgeleitet ist?

public class GenericClass<T> 
{ 
}  

public bool IsDeriveFrom(object o) 
{ 
    return o.GetType().IsSubclassOf(typeof(GenericClass)); //will throw exception here 
} 

Bitte beachten Sie, dass der obige Code eine Ausnahme auslöst. Der Typ der generischen Klasse kann nicht direkt abgerufen werden, da für eine generische Klasse kein Typ ohne einen angegebenen Typparameter angegeben ist.

Antwort

2

Ihr sollte so etwas tun:

public class GenericClass<T> 
    { 
    } 

    public class GenericClassInherited<T> : GenericClass<T> 
    { 
    } 


    public static bool IsDeriveFrom(object o) 
    { 
     return o.GetType().BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>); 
    } 

Beispiel:

static void Main(string[] args) 
    { 
     var generic = new GenericClassInherited<int>(); 
     var isTrue = IsDeriveFrom(generic); 
    } 
+1

, dass so viele Ausnahmen auslösen kann, wenn es nicht ein Basistyp ist, oder es ist nicht eine generische Typdefinition, und es schlägt fehl, wenn 'Bar: Foo: GenericFoo ' und auf und weiter. – jason

+0

Ich weiß aber in jedem Fall funktioniert es für obiges Beispiel. Und @Edison kann Ausnahmen hinzufügen, die sich selbst behandeln. Es ist nur eine Idee. –

+0

Ich habe den Beispielcode ausprobiert und einige Ausnahmen hinzugefügt. Es funktioniert jetzt perfekt. Andere Antworten hier gaben mir auch einige hilfreiche Informationen, aber ich weiß nicht, warum ich diesen nützlichen Antworten nicht zustimmen kann. –

2
bool IsDerivedFrom(Type type, Type genericBaseTypeDefinition) { 
    Contract.Requires(type != null); 
    Contract.Requires(genericBaseTypeDefinition != null); 
    Contract.Requires(genericBaseTypeDefinition.IsGenericBaseTypeDefinition); 
    Type baseType = type.BaseType; 
    if (baseType == null) { 
     return false; 
    } 

    if (baseType.IsGenericType) { 
     Type generic = baseType.GetGenericTypeDefinition(); 
     if (generic == null) { 
      return false; 
     } 
     return generic == genericBaseTypeDefinition; 
    } 

    return IsDerivedFrom(baseType, genericBaseTypeDefinition); 
} 

Verbrauch:

bool derived = IsDerivedFrom(typeof(Foo), typeof(GenericFoo<>)); 

Diese Prüfungen bestehen:

class GenericFoo<T> { } 
class DerivedGenericFoo<T> : GenericFoo<T> { } 
class Foo : GenericFoo<int> { } 
class Bar : Foo { } 
class Animal { } 

[Fact] 
public void DerivedGenericFoo_derives_from_open_GenericFoo() { 
    Assert.Equal(
     true, 
     IsDerivedFrom(
      typeof(DerivedGenericFoo<int>), 
      typeof(GenericFoo<>) 
     ) 
    ); 
} 

[Fact] 
public void Foo_derives_from_open_GenericFoo() { 
    Assert.Equal(true, IsDerivedFrom(typeof(Foo), typeof(GenericFoo<>))); 
} 

[Fact] 
public void Bar_derives_from_open_GenericFoo() { 
    Assert.Equal(true, IsDerivedFrom(typeof(Bar), typeof(GenericFoo<>))); 
} 

[Fact] 
public void Animal_does_not_derive_from_open_GenericFoo() { 
    Assert.Equal(false, IsDerivedFrom(typeof(Animal), typeof(GenericFoo<>))); 
} 
1

Der Schlüssel ist Type.GetGenericTypeDefinition. Hier ist ein komplettes Beispiel:

class Generic<T> { } 

class Derived<T> : Generic<T> { } 
class NonDerived<T> { } 

class Program 
{ 
    static bool IsDerivedFromGenericT(Type type) 
    { 
     if (!type.IsGenericType) 
      return false; 
     if (type.GetGenericTypeDefinition() == typeof(Generic<>)) 
      return true; 
     if (type.BaseType == null) 
      return false; 
     return IsDerivedFromGenericT(type.BaseType); 
    } 

    static void Main(string[] args) 
    { 
     var b1 = IsDerivedFromGenericT(new Derived<int>().GetType()); // true 
     var b2 = IsDerivedFromGenericT(new Derived<string>().GetType()); // true 
     var b3 = IsDerivedFromGenericT(new NonDerived<string>().GetType()); // false 
    } 
} 
+1

definitiv scheint dies ein besseres Beispiel –

Verwandte Themen