Необходимо проверить типы двух видов моделей, чтобы увидеть, происходят ли они из одной базы - PullRequest
2 голосов
/ 02 августа 2011

У меня есть ситуация, когда мне нужно проверить, происходят ли две модели представления из одной и той же базы.

Модель:

class BaseModel;
class DerivedModel1 : BaseModel;
class DerivedModel2 : BaseModel;
class DerivedModel3 : DerivedModel2;

Учитывая эту модель, я хочу знать, когда DerivedModel1и DerivedModel3 оба от одного и того же BaseModel.Не гарантируется, что эти классы находятся в одной сборке, а также может быть более глубокая иерархия.Также не гарантируется, что я знаю, что такое BaseModel.

Я пробовал DerivedModel1.GetType().IsAssignableFrom(DerivedModel3.GetType());, но, как вы уже знаете, это не сработает из-за глубины иерархии.

Любоймысли?

Ответы [ 3 ]

3 голосов
/ 02 августа 2011

Вы можете проверить это так:

bool DoBothDeriveFrom<TBase, T1, T2>()
{
    return typeof(T1).IsSubclassOf(typeof(TBase))
        && typeof(T2).IsSubclassOf(typeof(TBase));
}

IsAssignableFrom тоже будет работать, если вы предоставите общую базу, глубина иерархии тут не при чем.

Если TBase неизвестно, вы можете взобраться по деревьям наследования обоих классов, как предложено InBetween. А затем сравните оба дерева, чтобы проверить, имеют ли они общий тип, отличный от object. Это может выглядеть как-то так:

public bool HaveCommonRoot<T1, T2>()
{
    var tree1 = InheritanceTree<T1>();
    var tree2 = InheritanceTree<T2>();
    return tree1.Intersect(tree2).Any();
}

private IEnumerable<Type> InheritanceTree<T>()
{
    var type = typeof(T);
    yield return type;

    while (type.BaseType != typeof(object))
    {
        type = type.BaseType;
        yield return type;
    }
}
1 голос
/ 02 августа 2011

В основном вам нужен наибольший общий базовый тип иерархии типов.

Вот код для этого:

void Main()
{
    var t1 = typeof(DerivedModel1);
    var t3 = typeof(DerivedModel3);

    var t1Hierarchy = new LinkedList<Type>();
    var t3Hierarchy = new LinkedList<Type>();
    getHierarchy(t1, t1Hierarchy);
    getHierarchy(t3, t3Hierarchy);

    var pairs = t1Hierarchy.Zip(t3Hierarchy, Tuple.Create);
    var common = pairs.TakeWhile(p => p.Item1 == p.Item2);
    var gcd = common.LastOrDefault();
}

void getHierarchy(Type t, LinkedList<Type> bases)
{
    var baseType = t.BaseType;

    if (baseType == null)
    {
        return;
    }

    bases.AddFirst(baseType);
    getHierarchy(baseType, bases);
}

class BaseModel {}
class DerivedModel1 : BaseModel {}
class DerivedModel2 : BaseModel {}
class DerivedModel3 : DerivedModel2 {}
1 голос
/ 02 августа 2011

Почему бы не использовать Type.IsSubClassOf метод?Я не уверен, что этот метод вернет true для уровней глубокой иерархии (я думаю, что он делает, но не может проверить это в данный момент), или он вернет только true, если указанный тип является базовым типом immeadiate.Тем не менее, легко реализовать повторяющийся алгоритм для проверки дерева иерархии до тех пор, пока вы не достигнете базового типа object.

Еще одна вещь: вы не используете IsAssignableFrom правильно.В любом случае это должно быть:

BaseModel.GetType().IsAssignableFrom(DerivedModel3.GetType());

DerivedModel3 и DerivedModel1 не могут быть назначены, поскольку они не имеют никакого отношения между ними.Ближайший общий корень - BaseModel.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...