【发布时间】:2022-01-01 23:58:42
【问题描述】:
我想做的是改变 C# 方法在调用时的执行方式,这样我就可以编写如下内容:
[Distributed]
public DTask<bool> Solve(int n, DEvent<bool> callback)
{
for (int m = 2; m < n - 1; m += 1)
if (m % n == 0)
return false;
return true;
}
在运行时,我需要能够分析具有 Distributed 属性的方法(我已经可以这样做),然后在函数体执行之前和函数返回之后插入代码。更重要的是,我需要能够在不修改调用 Solve 的代码或函数开头(在编译时;在运行时这样做是目标)的情况下做到这一点。
目前我已经尝试了这段代码(假设t是Solve存储的类型,m是Solve的MethodInfo):
private void WrapMethod(Type t, MethodInfo m)
{
// Generate ILasm for delegate.
byte[] il = typeof(Dpm).GetMethod("ReplacedSolve").GetMethodBody().GetILAsByteArray();
// Pin the bytes in the garbage collection.
GCHandle h = GCHandle.Alloc((object)il, GCHandleType.Pinned);
IntPtr addr = h.AddrOfPinnedObject();
int size = il.Length;
// Swap the method.
MethodRental.SwapMethodBody(t, m.MetadataToken, addr, size, MethodRental.JitImmediate);
}
public DTask<bool> ReplacedSolve(int n, DEvent<bool> callback)
{
Console.WriteLine("This was executed instead!");
return true;
}
但是,MethodRental.SwapMethodBody 仅适用于动态模块;不是那些已经编译并存储在程序集中的。
所以我正在寻找一种方法来有效地对 已存储在已加载并正在执行的程序集中的方法执行 SwapMethodBody。
注意,如果我必须将方法完全复制到动态模块中,这不是问题,但在这种情况下,我需要找到一种方法来复制整个 IL 以及更新对 Solve() 的所有调用这样他们就会指向新的副本。
【问题讨论】:
-
无法交换已加载的方法。否则 Spring.Net 不必用代理和接口做奇怪的事情 :-) 阅读这个问题,它与你的问题相切:stackoverflow.com/questions/25803/…(如果你可以拦截它,你可以交换它......如果你不能 1 那么显然你不能 2)。
-
在这种情况下,有没有办法将方法复制到动态模块中,并更新程序集的其余部分,以便对该方法的调用指向新副本?
-
老老实实。如果可以轻松完成,那么所有各种 IoC 容器都可能会这样做。他们不这样做-> 99% 它不能完成:-)(没有可怕和无名的黑客)。只有一个希望:他们承诺在 C# 5.0 中进行元编程和异步。我们已经看到了异步......元编程什么都没有......但它可能是它!
-
你真的没有解释为什么要让自己陷入如此痛苦的境地。
-
请看下面我的回答。这是完全可能的。在您不拥有的代码上和运行时。我不明白为什么这么多人认为这是不可能的。
标签: c# methods assemblies cil