C#, универсальный, Как определить это T, является Основой <Tp>: где Tp: Основа <Tp> и Основа Вызова <Tp> метод

У меня есть запутывающая ситуация.

Основывайте Универсальный Тип и преемника

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 и исполнительный метод на нем. Как я могу сделать это????

1
задан sh1ng 22 July 2010 в 11:36
поделиться

3 ответа

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

class Foo<T> : BaseType<T>

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

.
1
ответ дан 2 September 2019 в 22:51
поделиться

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

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
ответ дан 2 September 2019 в 22:51
поделиться

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

EDIT: Я думаю, что вы застряли на использовании отражения. Если вы хотите иметь возможность писать код для конкретного типа, вы можете создать общий метод и вызвать его, используя отражение:

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
    }
}
0
ответ дан 2 September 2019 в 22:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: