我目前正在尝试通过将属性替换为一点IL来交换属性get实现。我将这个问题用作参考:How to replace a pointer to a pointer to a method in a class of my method inherited from the system class?
我唯一的区别是我的方法是通过MethodBuilder声明的:
MethodBuilder propertyGetBuilder = builder.DefineMethod
(
dynamicFunctionName,
MethodAttributes.Public,
propertyInfo.PropertyType,
Type.EmptyTypes
);
ILGenerator propertyGetIlGenerator = propertyGetBuilder.GetILGenerator();
propertyGetIlGenerator.Emit(OpCodes.Ldarg_0);
propertyGetIlGenerator.Emit(OpCodes.Ldstr, propertyInfo.Name);
propertyGetIlGenerator.Emit(OpCodes.Ldstr, relationKeyField.Name);
propertyGetIlGenerator.Emit(OpCodes.Ldstr, relationAttribute.RelationColumn);
propertyGetIlGenerator.Emit(OpCodes.Call, loadRelationMethod);
propertyGetIlGenerator.Emit(OpCodes.Ret);
这将新功能添加到名为BeforeGet{PropertyName}
的生成类型中>
生成新类型后,我将其实例化以确保内存地址存在:dynamic fakeType = Activator.CreateInstance(type);
我从现有类和新创建的BeforeGet{PropertyName}
fakeType类Type中检索propertyInfo GetMethod。
此函数之后同时使用了两个MethodInfo:
RuntimeHelpers.PrepareMethod(methodA.MethodHandle); RuntimeHelpers.PrepareMethod(methodB.MethodHandle); unsafe { if (IntPtr.Size == 4) { int* inj = (int*)methodA.MethodHandle.Value.ToPointer() + 2; int* tar = (int*)methodB.MethodHandle.Value.ToPointer() + 2; #if DEBUG Console.WriteLine("\nVersion x86 Debug?\n"); byte* injInst = (byte*)*inj; byte* tarInst = (byte*)*tar; int* injSrc = (int*)(injInst + 1); int* tarSrc = (int*)(tarInst + 1); *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5); #else *tar = *inj; #endif } else { long* inj = (long*)methodA.MethodHandle.Value.ToPointer() + 1; long* tar = (long*)methodB.MethodHandle.Value.ToPointer() + 1; #if DEBUG Console.WriteLine("\nVersion x64 Debug\n"); byte* injInst = (byte*)*inj; byte* tarInst = (byte*)*tar; int* injSrc = (int*)(injInst + 1); int* tarSrc = (int*)(tarInst + 1); *tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5); #else *tar = *inj; #endif } }
运行此代码后,我在程序中执行以下代码:
LoadedTag.Item.ItemID;
其中,LoadedTag是本应获得Item
Getter的新实现的类,但由于没有替换该函数,因此我得到了null引用异常。
但是,如果我在立即窗口中执行此代码,则确实设置了ItemID并调用了拦截函数。
[我认为问题是由于垃圾收集器删除了fakeType,该fakeType包含指向方法交换期间使用的函数的实际指针。如果是这样,我应该如何解决?
谢谢您!
如果需要,请查询完整代码,然后将其上传到Github。
我目前正在尝试通过将属性替换为一点IL来交换属性get实现。我以这个问题为参考:如何在我的类中替换指向方法的指针...
代码不清楚,但是:“ fakeType”与交换指针的位置是否在同一范围内?