gpt4 book ai didi

c# - 使用 Mono.Cecil 添加静态构造函数会导致 TypeInitializationException

转载 作者:行者123 更新时间:2023-11-30 23:18:31 25 4
gpt4 key购买 nike

我正在尝试使用 Mono Cecil 将静态构造函数添加到如下程序中:

namespace SimpleTarget
{
class C
{
public void M()
{
Console.WriteLine("Hello, World!");
}
}
}

下面的代码添加了静态构造器:

namespace AddStaticConstructor
{
class Program
{
static void Main(string[] args)
{
var assemblyPath = args[0];
var module = ModuleDefinition.ReadModule(assemblyPath);

var corlib = ModuleDefinition.ReadModule(typeof(object).Module.FullyQualifiedName);
var method = corlib.Types.First(t => t.Name.Equals("Console")).Methods.First(m => m.Name.Contains("WriteLine"));

var methodToCall = module.Import(method);

foreach (var type in module.Types)
{
if (!type.Name.Contains("C")) continue;

var staticConstructorAttributes =
Mono.Cecil.MethodAttributes.Private |
Mono.Cecil.MethodAttributes.HideBySig |
Mono.Cecil.MethodAttributes.Static |
Mono.Cecil.MethodAttributes.SpecialName |
Mono.Cecil.MethodAttributes.RTSpecialName;

MethodDefinition staticConstructor = new MethodDefinition(".cctor", staticConstructorAttributes, module.TypeSystem.Void);
type.Methods.Add(staticConstructor);

type.IsBeforeFieldInit = false;

var il = staticConstructor.Body.GetILProcessor();
il.Append(Instruction.Create(OpCodes.Ret));

Instruction ldMethodName = il.Create(OpCodes.Ldstr, type.FullName);
Instruction callOurMethod = il.Create(OpCodes.Call, methodToCall);

Instruction firstInstruction = staticConstructor.Body.Instructions[0];
// Inserts the callOurMethod instruction before the first instruction


il.InsertBefore(firstInstruction, ldMethodName);
il.InsertAfter(ldMethodName, callOurMethod);
}

module.Write(assemblyPath);
}
}
}

查看 dotPeek 中的反编译二进制文件,似乎一切都已正确设置。尝试使用修改后的 C 类型时,我得到一个 TypeInitializationException,内部异常为“System.InvalidProgramException:JIT 编译器遇到内部限制”

在使用静态构造函数之前,我还需要正确设置什么吗?

谢谢!

最佳答案

问题是您在这里得到了错误的 System.WriteLine 重载:

var corlib = ModuleDefinition.ReadModule(typeof(object).Module.FullyQualifiedName);
var method = corlib.Types.First(t => t.Name.Equals("Console")).Methods.First(m => m.Name.Contains("WriteLine"));
var methodToCall = module.Import(method);

使用这个简单的代码获取你想要使用的重载:

var wlMethod = typeof (Console).GetMethod(nameof(Console.WriteLine), new[] {typeof (string)});
var methodToCall = module.ImportReference(wlMethod);

关于c# - 使用 Mono.Cecil 添加静态构造函数会导致 TypeInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40848968/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com