【发布时间】:2019-03-09 07:29:56
【问题描述】:
考虑以下代码:
private class ThirdPartyClass {
private class InternalPrivateClass { }
private static InternalPrivateClass Init() {
return new InternalPrivateClass();
}
private static int DoSomething(InternalPrivateClass t1) {
return 0;
}
}
假设我无法控制ThirdPartyClass,并且以任何方式对其进行逆向工程都是成本高昂的。我希望能够快速调用DoSomething 而无需反射的性能开销。所以我到目前为止:
Type t = typeof(ThirdPartyClass);
object context = t.GetMethod("Init", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
MethodInfo mi = t.GetMethod("DoSomething", BindingFlags.NonPublic | BindingFlags.Static);
// ...now what?
- 调用
mi.Invoke(null, new object[]{context})当然很慢,因为它使用了反射。 -
Delegate.CreateDelegate(typeof(Func<object, int>), mi);fails 因为 Func 签名必须完全匹配并且 (object, int) 与 MethodInfo 的签名 (ThirdPartyClass.InternalPrivateClass, int) 不匹配 - 通过反射构造一个正确类型的委托(参见https://stackoverflow.com/a/40579063/2692950)只能让我调用
.DynamicInvoke(context),这仍然很慢。我不能将此委托转换为 Func 以便能够直接调用它,因为签名不匹配。 - 我不能写
Func<ThirdPartyClass.InternalPrivateClass, int>- 因为InternalPrivateClass是私有的,所以它不会编译。
解决了! (https://stackoverflow.com/a/52652398/2692950)
ᅟ
我为什么需要这个示例:
看看这个 MD4 哈希实现:https://stackoverflow.com/a/46821287/2692950 (缩短版:https://stackoverflow.com/a/52640221/2692950)
这很好用,除了每个散列操作都通过反射调用方法!
在这个例子中,我们通过反射调用一个不可访问的私有函数System.Security.Cryptography.Utils.HashEnd(SafeProvHandle h),传递一个SafeHandle作为参数。这是因为SafeProvHandle 继承自SafeHandle。 SafeProvHandle 无法直接引用,因为它是私有的,因此似乎无法直接调用此函数。
(我最感兴趣的是问题顶部的一般情况是否存在解决方案,但如果有人知道通过ALG_ID 直接获取加密服务提供商的更好方法,我我全神贯注:)
【问题讨论】:
-
间接解决方案:第三方库似乎是.NET。幸运的是,您可以从referencesource.microsoft.com/#mscorlib/system/security/…复制源代码,使其编译(不一定容易),然后根据需要进行修改。
-
这几乎涉及重新实现一大块 .NET。有更简单的方法来处理我的特定示例。我对一般情况更感兴趣。我意识到我很可能会要求一些不存在的东西,但尝试一下也无妨:)
-
我认为没有办法。你已经(我认为)意识到没有办法声明一个变量来保存你试图创建的东西。下一步是发出某种包装函数,它可以调用所需的函数,但本身不必传递
InternalPrivateClass。你可以存储某种Func准备调用它。但是发出这个函数面临着同样的障碍。 -
我添加了一段说明如何在不直接引用私有类型的情况下调用期望私有类型作为参数的私有方法。看起来这个问题的解决方案,如果存在的话,确实会涉及发射 IL。不幸的是,我对这方面的了解还不够。
-
您需要实例化的私有类是否像您给出的示例一样容易实例化? IE。公共无参数构造函数?您要编译的实际代码是(如果我们忽略私有修饰符):
var x = thirdPartyInstance.SomeFunc(new ThirdPartyClass.InternalPrivateClass());吗?我问是因为我有一些 IL 发射的经验,我可以尝试一起做一个小的尝试来做到这一点。
标签: c# .net reflection delegates func