正确调用涉及实例的ProvidedConstructor中的方法

9

我应该如何在生成类型提供程序中适当地为ProvidedConstructorInvokeCode提供代码,以实现以下内容?

给定:

module Utils =
    let someFun (s : string) (inst : obj) =
          // Does something here...
          ()

我需要生成的类型能够有效地执行以下操作:
type NewGeneratedType () as self =
     inherit BaseType ()

     do
         Utils.someFun "Foo" (box self)

我已经成功调用了基础构造函数,但不知道如何正确地切片实例并调用函数:

let ctor = ProvidedConstructor([])
let ci = baseType.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [|  |], null)
ctor.BaseConstructorCall <- fun args -> ci, args 

// I do not know how to properly call this to match the constructor above
ctor.InvokeCode <- fun args -> <@@ () @@>
3个回答

4

看起来这个参数是作为构造函数的最后一个参数传入的。

从那里开始,您的InvokeCode函数将被运行并返回翻译的引用。所以,我认为你只需要像这样做:

ctor.InvokeCode <- fun args -> <@@ let me = Seq.last args @@>

1
this 总是第一个。xs |> List.append x 等同于 List.append x xs,也等同于 x::xs - Sergey Tihon
请注意,尝试使用此功能始终会导致类型不匹配错误:将表达式拼接到引号文字中时出现类型不匹配。插入的表达式树的类型与拼接操作所期望的类型不匹配。期望的是“NewGeneratedType”,但收到的类型是“System.Object”。考虑使用预期的表达式类型进行类型注释,... 我尝试的所有方法似乎都无法解决这个问题。 - Reed Copsey
顺便提一下 - 这帮我实现了目标 - 发布了所需的内容在 https://dev59.com/0Jbfa4cB1Zd3GeqPyMGE#37172942 感谢 @CAIndy - Reed Copsey

4

我通过以下方法使它工作:

ctor.InvokeCode <- 
    fun args -> 
        let this = Seq.head args
        let boxed = Expr.Coerce(this, typeof<obj>)
        <@@  Utils.someFun "Foo" %%(boxed) @@>

请注意,尝试将前两行移入splice中会导致各种错误,但当我将其拉出时,它可以完美地工作。

1

@Reed Copsey,我认为你实际上需要调用自己的构造函数:

假设NewGeneratedType是您已经定义的具体类型

<@@ let this = (ctor.Invoke([||])) :> NewGeneratedType
    Utils.someFun "foo" (box this)
@@>

如果NewGeneratedType未定义但也是提供的类型本身,则需要使用Expr.Coerce:
<@@ let this = (ctor.Invoke([||]))
    let thisTyped = %%Expr.Coerce(this, providedType)
    Utils.someFun "foo" (box this)
@@>

我不是100%确定这个函数,但我希望这能帮助你走上正确的道路。


不幸的是,添加 ctor.Invoke 报告错误 ... 在生成的方法中报告了一个错误:未知常量 'ProviderImplementation.ProvidedTypes.ProvidedConstructor' - Reed Copsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接