Reputation: 6502
so I have inheritance chain like this:
class a : {}
class a<T> : {}
class b: a<int> {}
class c: a {}
and I need to check if instance (let's say var inst = new b()
) inherited from a<>
or from a
only.
however, nothing of standard IsAssignableFrom
, IsSubclassOf
, IsInstanceOfType
, is
don't fit.
What is a proper way to do this?
UPD1: Inheritance chain could be deeper than 1 level
Upvotes: 3
Views: 402
Reputation:
class a : {}
class a<T> : {}
I'm sorry, but in C# a
and a<T>
are completely different. The fact that they both start with the letter a
is a coincidence.
So to tell the difference, you can use the is operator.
if (inst is a)
{
// derived from a
}
else
{
// not derived from a
}
Upvotes: 0
Reputation: 37770
Assuming, that you have this hierarchy:
class a { }
class a<T> : a { }
class b : a<int> { }
class c : a { }
you need to explore inheritance tree to get base generic types and test their generic type definitions. But if you looking for some generic-purpose solution, you have to take into account interface implementation case.
E.g., if your hierarchy will be rewritten like this:
interface a { }
interface a<T> : a { }
class b : a<int> { }
class c : a { }
this will "break" inheritance tree traversal, because base type of b
will be System.Object
instead of a<T>
. That is, inheritance and interface implementations are two different things.
I'd implement it this way:
internal static class TypeExtensions
{
private static bool IsInheritedFromGenericTypeDefinition(Type type, Type baseType)
{
do
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == baseType)
return true;
type = type.BaseType;
}
while (type != null);
return false;
}
public static bool IsInheritedFrom(this Type type, Type baseType)
{
if (baseType.IsGenericTypeDefinition)
{
if (!type.IsInterface && baseType.IsInterface)
{
do
{
// since baseType is an interface, and source type is not,
// we can't test inheritance tree anymore;
// instead, we have to obtain implemented interfaces and test them
var implementedInterfaces = type.GetInterfaces();
if (implementedInterfaces.Any(intf => IsInheritedFromGenericTypeDefinition(intf, baseType)))
return true;
type = type.BaseType;
}
while (type != null);
return false;
}
else
return IsInheritedFromGenericTypeDefinition(type, baseType);
}
return baseType.IsAssignableFrom(type);
}
}
Results:
a -> a<> = True
b -> a<> = True
b -> a = True
b -> a = Truec -> a = True
c -> a<> = False
Upvotes: 1
Reputation: 28272
With your update (more inheritance levels), you could have this:
public static bool IsGenericA(object instance)
{
Type t = instance.GetType();
while(t.BaseType != null && t.BaseType != typeof(object))
t = t.BaseType;
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(a<>);
}
public static bool IsNonGenericA(object instance)
{
Type t = instance.GetType();
while(t.BaseType != null && t.BaseType != typeof(object))
t = t.BaseType;
return t == typeof(a);
}
See it in action in this fiddle
Should work for any levels as long as the base is a
or a<something>
Upvotes: 1
Reputation: 43513
A instance of class b is not derived from a<T>
, but from a<int>
, the two are different types.
var type = inst.GetType();
var result = false;
while (type != typeof(object))
{
type = type.BaseType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(a<>))
{
result = true;
break;
}
}
//check result
Upvotes: 3
Reputation: 18013
b
is not inherited from a<>
, it is inherited from a<int>
. However, you can check by reflection whether the generic type definition of the base class is a<>
:
type t = typeof(b).BaseType;
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(a<>);
Upvotes: 1
Reputation: 889
how about typeOf() ? you can get parent classes using this
Upvotes: 0