我可以使用这样的函数body中间语言:
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();我能够修改它的IL代码,以便在执行方法主体之前调用以下方法OnChangeField
public static void OnChangeField()
{
Console.WriteLine("VICTORY");
return;
}到目前为止我是这样做的:
我将调用指令定义为要调用的方法:
MethodInfo OnStfld = typeof(MethodBoundaryAspect).GetMethod("OnChangeField");
byte[] callIL = new byte[5];
callIL[0] = (byte)OpCodes.Call.Value;
callIL[1] = (byte)(OnStfld.MetadataToken & 0xFF);
callIL[2] = (byte)(OnStfld.MetadataToken >> 8 & 0xFF);
callIL[3] = (byte)(OnStfld.MetadataToken >> 16 & 0xFF);
callIL[4] = (byte)(OnStfld.MetadataToken >> 24 & 0xFF);注意,OnChangeField位于MethodBoundaryAspect类中。该类位于编辑的方法程序集之外。
我就是这样修改原始(NestedFoo(...))方法主体的:
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
InjectionHelper.UpdateILCodes(NestedFooInfo, callIL.Concat(ilCodes).ToArray());我得到了一个:
System.BadImageFormatException:“未找到索引”( HRESULT: 0x80131124中的例外)
但是,只有在挂钩方法OnChangeField在外部(至少我理解)的情况下,执行才是可靠的。如果我将OnChangeField移动到与NestedFoo相同的类中,或者在NestedFoo的程序集的另一个类中,它将完美地工作。
据我所知,元数据指向一个无效的内存位置。有办法改变这种状况吗?
这里的引用是:修改后的方法的方法主体是什么样子的:
public class ExceptionHandlingService : IExceptionHandlingService
{
public static string var1 = "initialValue";
public static string Var2 { get; set; } = "initialValue";
public string var3 = "initialValue";
public string Var4 { get; set; } = "initialValue";
public string NestedFoo(SampleClass bar)
{
var1 = "value set in NestedFoo()";
Var2 = "value set in NestedFoo()";
var3 = "value set in NestedFoo()";
Var4 = "value set in NestedFoo()";
AddPerson("From", "NestedFoo", 2);
return Foo();
}
[...]
}以及我如何称之为改变的方法:
var a = new ExceptionHandlingService();
var b = new SampleClass("bonjour", 2, 3L); // Not really relevant
a.NestedFoo(b);对于那些想知道InjectionHelper.UpdateILCodes(NestedFooInfo, newIlCodes);中会发生什么的人,您可以检查此链接,它显示了如何在运行时编辑Il代码。
发布于 2020-11-24 14:57:29
您需要向MemberRef和连续的TypeRef或TypeSpec元数据表添加记录,以包含对类型的引用并引用这些标记。这也涉及到正确地写签名点。
参见分区II 22.38,22.25 of ECMA-335
https://stackoverflow.com/questions/64891113
复制相似问题