2010-12-30 12 views
6

Załóżmy, że mam obiekt, a następnie skąd mogłem wiedzieć, czy obiekt pochodzi z określonej klasy ogólnej. Na przykład:Skąd mogę wiedzieć, czy obiekt pochodzi z określonej klasy ogólnej?

public class GenericClass<T> 
{ 
}  

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

Proszę zauważyć, że powyższy kod wygeneruje wyjątek. Typ klasy ogólnej nie może być pobrany bezpośrednio, ponieważ nie ma typu dla klasy ogólnej bez dostarczonego parametru typu.

Odpowiedz

2

Twój powinien zrobić coś takiego:

public class GenericClass<T> 
    { 
    } 

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


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

Przykład:

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

To może rzucać tak wiele wyjątków, gdy nie jest to typ bazowy, albo nie jest ogólną definicję typu, a nie kiedy 'Bar: Foo: GenericFoo ' a na i dalej. – jason

+0

Wiem, ale w każdym razie działa na powyższym przykładzie. A @Edison może dodawać wyjątki do siebie. To tylko pomysł. –

+0

Próbowałem kodu przykładowego i dodałem kod obsługi wyjątków. Teraz działa idealnie. Inne odpowiedzi tutaj również dały mi pomocne informacje, ale nie wiem, dlaczego nie mogę głosować na te przydatne odpowiedzi. –

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); 
} 

Zastosowanie:

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

Testy te pass:

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

Kluczem jest Type.GetGenericTypeDefinition. Oto pełna przykład:

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

zdecydowanie, wydaje się to lepszym przykładem –

Powiązane problemy