代码之家  ›  专栏  ›  技术社区  ›  sh1ng

C通用如何定义t is base<tp>:其中tp:base<tp>和call base<tp>方法

  •  1
  • sh1ng  · 技术社区  · 14 年前

    我的处境很混乱。

    基泛型类型和后续类型

    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 回复  |  直到 14 年前
        1
  •  1
  •   Jon Skeet    14 年前

    您可以使用反射并使用 Type.BaseType . 请注意,根据具体的具体类,基类型仍然可以是开放的泛型类型,例如

    class Foo<T> : BaseType<T>
    

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

        2
  •  1
  •   Steven    14 年前

    您可以使用以下代码:

    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;
    }
    
        3
  •  0
  •   Quartermeister    14 年前

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