Получить все производные методы метода - PullRequest
0 голосов
/ 14 июня 2019

Учитывая метод в C#, мне нужно найти все методы в подклассах, которые прямо или косвенно переопределяют этот метод.

Например, учитывая следующую архитектуру класса

abstract class A { public abstract void m(); }
class B : A { public override void m(){}; }
class C : A { public override void m(){}; }
class D : C { public override void m(){}; }
class E : C { public override void m(){}; }
class F : E { public override void m(){}; }
class G : C {  }
class H : G { public override void m(){}; }

Тогда производные методы C.m будут такими же, как и у классов D, E, F, H.

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

    public static IEnumerable<MethodInfo> DerivedMethods(this MethodInfo mi)
    {
        return mi.DeclaringType.Assembly.GetTypes()
            .Where(klass => klass.IsSubclassOf(mi.DeclaringType))
            .Select(subclass => subclass.GetMethods(
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
                .SingleOrDefault(m => m.GetBaseDefinition() == mi.GetBaseDefinition()))
            .Where(x => x != null);
    }

1 Ответ

0 голосов
/ 18 июня 2019

Один из способов сделать его немного более компактным - использовать вместо этого ключевые слова LINQ.

А вызов SingleOrDefault немного избыточен.Для каждого класса может быть не более одного переопределения.

Кроме того, я заметил, что ваш код работает только для базовых классов . Интерфейсы работают немного по-другому, не уверены, хотите ли вы реализовать это тоже?

public static IEnumerable<MethodInfo> DerivedMethods(this MethodInfo mi)
{
    Type baseType = mi.DeclaringType;
    IEnumerable<Type> subClasses = baseType.Assembly.GetTypes().Where((klass) => klass != baseType && baseType.IsAssignableFrom(klass));
    if (baseType.IsInterface) {
        return from klass in subClasses
               where !klass.IsInterface
               let map = klass.GetInterfaceMap(baseType)
               select map.TargetMethods[Array.IndexOf(map.InterfaceMethods, mi)];
    }
    else {
        return from klass in subClasses
               where !klass.IsAbstract // include this only if you want instantiable classes
               from m in klass.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
               where m.GetBaseDefinition() == mi.GetBaseDefinition()
               select m;
    }
}

Если вы хотите расширить поиск по всем сборкам в решении, вы бы изменилиsubClasses до:

    IEnumerable<Type> subClasses = from asm in AppDomain.CurrentDomain.GetAssemblies()
                                   from klass in asm.GetTypes()
                                   where klass != baseType && baseType.IsAssignableFrom(klass)
                                   select klass;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...