C# 使用Mono.Cecil添加静态构造函数会导致TypeInitializationException
我正在尝试使用Mono Cecil向程序添加静态构造函数,如下所示:C# 使用Mono.Cecil添加静态构造函数会导致TypeInitializationException,c#,cil,mono.cecil,C#,Cil,Mono.cecil,我正在尝试使用Mono Cecil向程序添加静态构造函数,如下所示: namespace SimpleTarget { class C { public void M() { Console.WriteLine("Hello, World!"); } } } 以下代码添加了静态构造函数: namespace AddStaticConstructor { class Program {
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.InvalidProgrameException:JIT编译器遇到内部限制”
在使用静态构造函数之前,是否还需要正确设置其他内容
谢谢 问题是您获得了错误的
系统重载。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);
请发一封邮件。不,这不是问题所在。是的,像你提到的那样写会更好,但它也会像他写的那样工作。他刚刚得到了第一个
WriteLine
方法,但这并不重要,因为他没有向它传递任何参数。你不必存储用ldstr
加载的字符串,你可以直接使用它们。如果你使用它,就可以了。但他没有。现在我明白你的意思了。是的,你写。为了解决这个问题,他可以按照我写的做,或者像你的答案一样使用它。