假设我有一个对象,那么我怎么知道该对象是否来自特定的泛型类。例如:
public class GenericClass<T>
{
}
public bool IsDeriveFrom(object o)
{
return o.GetType().IsSubclassOf(typeof(GenericClass)); //will throw exception here
}
请注意上面的代码会引发异常。无法直接检索泛型类的类型,因为没有提供类型参数的泛型类没有类型。
答案 0 :(得分:2)
你应该这样做:
public class GenericClass<T>
{
}
public class GenericClassInherited<T> : GenericClass<T>
{
}
public static bool IsDeriveFrom(object o)
{
return o.GetType().BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>);
}
示例:
static void Main(string[] args)
{
var generic = new GenericClassInherited<int>();
var isTrue = IsDeriveFrom(generic);
}
答案 1 :(得分: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);
}
用法:
bool derived = IsDerivedFrom(typeof(Foo), typeof(GenericFoo<>));
这些测试通过:
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<>)));
}
答案 2 :(得分:1)
关键是Type.GetGenericTypeDefinition
。这是一个完整的例子:
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
}
}