I have confusing situation.
Base Generic Type and successor
public abstract class BaseType<TEntity> : where TEntity : BaseType<TEntity>
public class AnyType : BaseType<AnyType>
It looks like a generic loop)))
I need Method like
public void Method<T>(T data)
{
if(typeof(T).IsSubclassOf(BaseType<????>))
convert data to BaseType<???> and exec BaseType<>'s method
else
//Do that
}
In generic Method i need to defines that T is BaseType and exec method on it. How can I do开发者_高级运维 that????
You can use reflection and work your way up the hierarchy using Type.BaseType
. Note that depending on the exact concrete class, the base type could still be an open generic type, e.g.
class Foo<T> : BaseType<T>
You can use Type.IsGenericTypeDefinition
and Type.GetGenericTypeDefinition
to try to work your way to BaseType<>
. Basically you want to find out whether any class in the inheritance hierarchy has a generic type definition which is typeof(BaseType<>)
. Just be glad you're not dealing with interfaces, which make the whole thing even harder :)
You can use the following code:
static bool IsBaseType<T>()
{
var t = typeof(T);
do
{
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(BaseType<>))
{
return true;
}
t = t.BaseType;
}
while (t != null);
return false;
}
A common pattern in this case is to have a non-generic base type of the generic base type. If your method doesn't involve the type parameter, then you're done. If it does, you could add a non-generic method that does a typecast, similar to Object.Equals:
public abstract class ReallyBaseType
{
public abstract void SomeMethod();
public abstract void SomeMethodWithParameter(object o);
}
public abstract class BaseType<TEntity> : ReallyBaseType
where TEntity : BaseType<TEntity>
{
public override void SomeMethodWithParameter(object o)
{
SomeMethodWithParameter((TEntity)o);
}
public abstract void SomeMethodWithParameter(TEntity entity);
}
public class AnyType : BaseType<AnyType>
{
public override void SomeMethod() { }
public override void SomeMethodWithParameter(AnyType entity) { }
}
Then, you can just check the actual type of data:
public void Method<T>(T data)
{
if (data is ReallyBaseType)
{
((ReallyBaseType)(object)data).SomeMethod();
}
}
EDIT: I think you're stuck using reflection, then. If you want to be able to write code against the concrete type, you could create a generic method and invoke it using reflection:
public class TestClass
{
private static MethodInfo innerMethodDefinition =
typeof(TestClass).GetMethod("InnerMethod");
public void Method(object data)
{
var t = data.GetType();
while (t != null &&
!(t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof(BaseType<>)))
{
t = t.BaseType;
}
if (t != null &&
t.GetGenericArguments()[0].IsAssignableFrom(data.GetType()))
{
innerMethodDefinition.MakeGenericMethod(
t.GetGenericArguments()[0]).Invoke(this, new object[] { data });
}
}
public void InnerMethod<TEntity>(TEntity data)
where TEntity : BaseType<TEntity>
{
// Here you have the object with the correct type
}
}
精彩评论