简体   繁体   English

如何通过反射从不同程序集中调用带有内部委托参数的内部方法?

[英]How to call internal method with internal delegate argument from different assembly by reflection?

I do not have a source code for a type and need to call an internal method with an internal argument. 我没有类型的源代码,需要使用内部参数调用内部方法。

Is there a way to do something like this: Set.InOrderTreeWalk((object o) => o != null) ? 有没有办法做这样的事情: 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;
        }
    }
}

Before I get into it, insert standard disclaimer about how implementation details are internal for a reason and the author doesn't owe you an explanation if something changes and it breaks your reflection code. 在我开始讨论之前,请插入一个标准的免责声明,说明实施细节如何内部存在的原因,并且作者不会欠您任何解释,以防发生某些更改并破坏了反射代码。


On the surface, the fact that the argument is of an internal delegate type does make this a bit troublesome, but there's actually a convenient way to get it: get the MethodInfo for the method we want to call and then examine its parameter. 从表面上看,参数是内部委托类型的事实确实使这有些麻烦,但是实际上有一种方便的方法来获取它:获取要调用的方法的MethodInfo ,然后检查其参数。

Let's assume we already have this variable with an instance assigned: 假设我们已经为这个变量分配了一个实例:

Set<MyNode> set;

...and that the MyNode type has been declared somewhere. ...并且MyNode类型已在某处声明。 We want Set<MyNode>.InOrderTreeWalk to call the following method for each node in the set: 我们希望Set<MyNode>.InOrderTreeWalk为集合中的每个节点调用以下方法:

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

There's not much to it, just follow the comments: 没什么大不了的,只需遵循以下注释即可:

// 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 });

Assuming you've provided enough information about the component you're using, and barring any issues with trust level, that should do it. 假设您已经提供了有关正在使用的组件的足够信息,并且排除了信任级别的任何问题,那么应该做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM