以下是我的Package
类的定义:
type Package ([<ParamArray>] info : Object[]) =
do
info |> Array.iter (Console.WriteLine)
member this.Count = info.Length
这是IL,我正在尝试:
let ilGen = methodbuild.GetILGenerator()
ilGen.Emit(OpCodes.Ldstr, "This is 1")
ilGen.Emit(OpCodes.Ldstr, "Two")
ilGen.Emit(OpCodes.Ldstr, "Three")
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object[]>|]))
ilGen.Emit(OpCodes.Ret)
但这似乎不起作用。我试过了:
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<String>; typeof<String>; typeof<String>|]))
a well as:
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object>; typeof<Object>; typeof<Object>|]))
但它只是嘲笑我。我做错了什么?
答案 0 :(得分:5)
[<ParamArray>]
属性向编译器指示方法接受可变数量的参数。但是,CLR并不真正支持varargs
方法 - 它只是C#/ VB.NET / F#编译器提供的语法糖。
现在,如果你带走了[<ParamArray>]
,你剩下的是什么?
(info : Object[])
这是你试图调用的构造函数的签名。
因此,您需要使用newarr
和stelem
操作码来创建数组,将值存储到其中,然后使用数组作为 论点。这应该做你想要的(虽然我没有测试过):
let ilGen = methodbuild.GetILGenerator()
// Create the array
ilGen.Emit(OpCodes.Ldc_I4_3)
ilGen.Emit(OpCodes.Newarr, typeof<obj>)
// Store the first array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_0)
ilGen.Emit(OpCodes.Ldstr, "This is 1")
ilGen.Emit(OpCodes.Stelem_Ref)
// Store the second array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_1)
ilGen.Emit(OpCodes.Ldstr, "Two")
ilGen.Emit(OpCodes.Stelem_Ref)
// Store the third array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_2)
ilGen.Emit(OpCodes.Ldstr, "Three")
ilGen.Emit(OpCodes.Stelem_Ref)
// Call the constructor
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object[]>|]))
ilGen.Emit(OpCodes.Ret)
注意:在此代码中,我使用dup
OpCode来避免在存储元素值时创建一个局部变量来保存数组引用。这是可行的,因为这段代码相当简单 - 我强烈建议你创建一个局部变量来保存数组引用,如果你想构建更复杂的东西。