C # generic Как определить, что T является Base <Tp>: где Tp: Base <Tp>и Call Base <Tp>метод - PullRequest
1 голос
/ 22 июля 2010

У меня запутанная ситуация.

Базовый универсальный тип и преемник

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 ]

1 голос
/ 22 июля 2010

Вы можете использовать следующий код:

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;
}
1 голос
/ 22 июля 2010

Вы можете использовать отражение и продвигаться вверх по иерархии, используя Type.BaseType. Обратите внимание, что в зависимости от конкретного конкретного класса базовый тип все еще может быть открытым универсальным типом, например

class Foo<T> : BaseType<T>

Вы можете использовать Type.IsGenericTypeDefinition и Type.GetGenericTypeDefinition, чтобы попытаться проложить себе путь к BaseType<>. По сути, вы хотите выяснить, имеет ли какой-либо класс в иерархии наследования определение общего типа, равное typeof(BaseType<>). Просто будьте рады, что вы не имеете дело с интерфейсами, которые делают все это еще сложнее:)

0 голосов
/ 22 июля 2010

Распространенный шаблон в этом случае - иметь неуниверсальный базовый тип общего базового типа.Если ваш метод не включает параметр типа, то все готово.Если это так, вы можете добавить неуниверсальный метод, который выполняет приведение типа, аналогично 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
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...