Как вызвать внутренний метод с внутренним аргументом делегата от другой сборки отражением? - PullRequest
0 голосов
/ 22 февраля 2019

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

Есть ли способ сделать что-то вроде этого: Set.InOrderTreeWalk((object o) => o != null)?

namespace assembly_1
{
    internal delegate bool TreeWalkPredicate<T>(Set<T>.Node node);
    public class Set<T>
    {
        private Node[] nodes;
        internal bool InOrderTreeWalk(TreeWalkPredicate<T> action)
        {
            foreach (var node in nodes)
            {
                if (!action(node))
                    return false;
            }

            return true;
        }

        internal class Node
        {
            public T Item;
        }
    }
}

1 Ответ

0 голосов
/ 27 февраля 2019

Прежде чем я углублюсь в это, вставьте стандартный отказ от ответственности о том, как детали реализации являются внутренними по какой-то причине, и автор не должен вам объяснять, если что-то изменится и это нарушит ваш код отражения.


На первый взгляд, тот факт, что аргумент имеет внутренний тип делегата, делает это немного проблематичным, но на самом деле есть удобный способ его получить: получить MethodInfo для метода, который мы хотим вызватьи затем исследуем его параметр.

Давайте предположим, что у нас уже есть эта переменная с назначенным экземпляром:

Set<MyNode> set;

... и что тип MyNode был объявлен где-то.Мы хотим, чтобы Set<MyNode>.InOrderTreeWalk вызывал следующий метод для каждого узла в наборе:

private bool MyPredicate(Set<MyNode>.Node node)
{
    return true;
}

Ничего особенного, просто следуйте комментариям:

// Get the method we want to call.
MethodInfo inOrderTreeWalkMethod = set.GetType().GetMethod(
    "InOrderTreeWalk", BindingFlags.NonPublic | BindingFlags.Instance);

// Get the internal delegate type from the parameter info.  The type retrieved here
// is already close-constructed so we don't have to do any generic-related manipulation.
Type treeWalkPredicateType = inOrderTreeWalkMethod.GetParameters()[0].ParameterType;

// Get the method we want to be called for each node.
MethodInfo myPredicateMethod = GetType().GetMethod(
    nameof(MyPredicate), BindingFlags.NonPublic | BindingFlags.Instance);

// Create the delegate.  This is where the magic happens.  The runtime validates
// type compatibility and throws an exception if something's wrong.
Delegate myPredicateDelegate = myPredicateMethod.CreateDelegate(treeWalkPredicateType, this);

// Call the internal method and pass our delegate.
bool result = (bool)inOrderTreeWalkMethod.Invoke(set, new object[] { myPredicateDelegate });

Предполагая, что выпредоставил достаточно информации о компоненте, который вы используете, и за исключением проблем с уровнем доверия, которые должны это сделать.

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