为什么 Mono.Cecil HelloWorld 示例失败并出现异常?
Why does the Mono.Cecil HelloWorld example fail with an exception?
open System
open Mono.Cecil
open Mono.Cecil.Cil
let myHelloWorldApp =
AssemblyDefinition.CreateAssembly(
new AssemblyNameDefinition("HelloWorld", new Version(1, 0, 0, 0)), "HelloWorld", ModuleKind.Console)
let module_ = myHelloWorldApp.MainModule
// create the program type and add it to the module
let programType =
new TypeDefinition("HelloWorld", "Program",
Mono.Cecil.TypeAttributes.Class ||| Mono.Cecil.TypeAttributes.Public, module_.TypeSystem.Object)
module_.Types.Add(programType)
// add an empty constructor
let ctor =
new MethodDefinition(".ctor", Mono.Cecil.MethodAttributes.Public ||| Mono.Cecil.MethodAttributes.HideBySig
||| Mono.Cecil.MethodAttributes.SpecialName ||| Mono.Cecil.MethodAttributes.RTSpecialName, module_.TypeSystem.Void)
// create the constructor's method body
let il = ctor.Body.GetILProcessor()
il.Append(il.Create(OpCodes.Ldarg_0))
// call the base constructor
il.Append(il.Create(OpCodes.Call, module_.ImportReference(typeof<obj>.GetConstructor([||]))))
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ret))
programType.Methods.Add(ctor)
// define the 'Main' method and add it to 'Program'
let mainMethod =
new MethodDefinition("Main",
Mono.Cecil.MethodAttributes.Public ||| Mono.Cecil.MethodAttributes.Static, module_.TypeSystem.Void)
programType.Methods.Add(mainMethod)
// add the 'args' parameter
let argsParameter =
new ParameterDefinition("args",
Mono.Cecil.ParameterAttributes.None, module_.ImportReference(typeof<string[]>))
mainMethod.Parameters.Add(argsParameter);
// create the method body
il = mainMethod.Body.GetILProcessor()
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ldstr, "Hello World"))
let writeLineMethod =
il.Create(OpCodes.Call,
module_.ImportReference(typeof<Console>.GetMethod("WriteLine", [|typeof<string>|])))
// call the method
il.Append(writeLineMethod)
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ret))
// set the entry point and save the module
myHelloWorldApp.EntryPoint <- mainMethod
我从那个问题的答案中借用了 并用 F# 重写了它。当我尝试 运行 它时,出现以下错误:
Unhandled Exception: System.TypeLoadException: Could not load type 'HelloWorld.Program' from assembly 'Hello
on=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'Main' has no implementation (no RVA).
这里有什么问题?
我猜测问题是由以下行引起的:
// create the method body
il = mainMethod.Body.GetILProcessor()
在 C# 中,这会将 Main
方法的 IL 处理器分配给 il
变量,但在 F# 中,这只是一个等式测试,结果是 false
-因此,您要为 Main
方法生成的 IL 代码被添加到构造函数的前一个 il
处理器中。
您应该可以使用变量阴影解决此问题:
// create the method body
let il = mainMethod.Body.GetILProcessor()
open System
open Mono.Cecil
open Mono.Cecil.Cil
let myHelloWorldApp =
AssemblyDefinition.CreateAssembly(
new AssemblyNameDefinition("HelloWorld", new Version(1, 0, 0, 0)), "HelloWorld", ModuleKind.Console)
let module_ = myHelloWorldApp.MainModule
// create the program type and add it to the module
let programType =
new TypeDefinition("HelloWorld", "Program",
Mono.Cecil.TypeAttributes.Class ||| Mono.Cecil.TypeAttributes.Public, module_.TypeSystem.Object)
module_.Types.Add(programType)
// add an empty constructor
let ctor =
new MethodDefinition(".ctor", Mono.Cecil.MethodAttributes.Public ||| Mono.Cecil.MethodAttributes.HideBySig
||| Mono.Cecil.MethodAttributes.SpecialName ||| Mono.Cecil.MethodAttributes.RTSpecialName, module_.TypeSystem.Void)
// create the constructor's method body
let il = ctor.Body.GetILProcessor()
il.Append(il.Create(OpCodes.Ldarg_0))
// call the base constructor
il.Append(il.Create(OpCodes.Call, module_.ImportReference(typeof<obj>.GetConstructor([||]))))
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ret))
programType.Methods.Add(ctor)
// define the 'Main' method and add it to 'Program'
let mainMethod =
new MethodDefinition("Main",
Mono.Cecil.MethodAttributes.Public ||| Mono.Cecil.MethodAttributes.Static, module_.TypeSystem.Void)
programType.Methods.Add(mainMethod)
// add the 'args' parameter
let argsParameter =
new ParameterDefinition("args",
Mono.Cecil.ParameterAttributes.None, module_.ImportReference(typeof<string[]>))
mainMethod.Parameters.Add(argsParameter);
// create the method body
il = mainMethod.Body.GetILProcessor()
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ldstr, "Hello World"))
let writeLineMethod =
il.Create(OpCodes.Call,
module_.ImportReference(typeof<Console>.GetMethod("WriteLine", [|typeof<string>|])))
// call the method
il.Append(writeLineMethod)
il.Append(il.Create(OpCodes.Nop))
il.Append(il.Create(OpCodes.Ret))
// set the entry point and save the module
myHelloWorldApp.EntryPoint <- mainMethod
我从那个问题的答案中借用了
Unhandled Exception: System.TypeLoadException: Could not load type 'HelloWorld.Program' from assembly 'Hello
on=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'Main' has no implementation (no RVA).
这里有什么问题?
我猜测问题是由以下行引起的:
// create the method body
il = mainMethod.Body.GetILProcessor()
在 C# 中,这会将 Main
方法的 IL 处理器分配给 il
变量,但在 F# 中,这只是一个等式测试,结果是 false
-因此,您要为 Main
方法生成的 IL 代码被添加到构造函数的前一个 il
处理器中。
您应该可以使用变量阴影解决此问题:
// create the method body
let il = mainMethod.Body.GetILProcessor()