C#generic如何定义T是Base <tp>:其中Tp:Base <tp>和Call Base <tp>方法</tp> </tp> </tp>

时间:2010-07-22 10:05:14

标签: c# generic-programming generics

我的情况很混乱。

基础通用类型和后继者

public abstract class BaseType<TEntity> : where TEntity : BaseType<TEntity>
public class AnyType : BaseType<AnyType>

看起来像一个通用循环)))

我需要像

这样的方法
public void Method<T>(T data)
{
if(typeof(T).IsSubclassOf(BaseType<????>))
 convert data to BaseType<???> and exec BaseType<>'s method
else
//Do that
}

在泛型方法中,我需要定义T是BaseType和exec方法。 我怎么能这样做????

3 个答案:

答案 0 :(得分:1)

您可以使用反射,并使用Type.BaseType在层次结构中向上工作。请注意,根据具体的具体类,基类型仍然可以是开放的泛型类型,例如

class Foo<T> : BaseType<T>

您可以使用Type.IsGenericTypeDefinitionType.GetGenericTypeDefinition尝试前往BaseType<>。基本上,您希望了解继承层次结构中的任何类是否具有typeof(BaseType<>)的泛型类型定义。只是很高兴你没有处理接口,这使整个事情变得更加困难:)

答案 1 :(得分:1)

您可以使用以下代码:

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

答案 2 :(得分:0)

在这种情况下,常见的模式是具有通用基类型的非泛型基类型。如果您的方法不涉及类型参数,那么您就完成了。如果是,您可以添加一个非泛型方法进行类型转换,类似于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) { }
}

然后,您可以检查实际的数据类型:

public void Method<T>(T data)
{
    if (data is ReallyBaseType)
    {
        ((ReallyBaseType)(object)data).SomeMethod();
    }
}

编辑:我认为你坚持使用反射,然后。如果您希望能够针对具体类型编写代码,则可以创建泛型方法并使用反射调用它:

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