vid*_*idi 4 f# quotations type-providers
我有一个类型提供程序,它给出了错误"将表达式拼接到引号文字时类型不匹配".
我提取下面的代码,以便在较小的上下文中重现该问题.
let f (s : string) : string = s //some dummy implementation
let t = ProvidedTypeDefinition(asm, ns, "Root", Some typeof<obj>)
let ctor = ProvidedConstructor(parameters = [],
InvokeCode = (fun args -> <@@ "root" :> obj @@>)) :> MemberInfo
let prop = ProvidedProperty(propertyName = "SomeProperty",
parameters = [],
propertyType = typeof<string>,
GetterCode = (fun args -> <@@ f %%(args.[0]) @@>)) :> MemberInfo
do t.AddMembers [ctor; prop]
t.SetBaseType typeof<obj>
Run Code Online (Sandbox Code Playgroud)
...当我使用类型提供者时
let root = Provided.Root()
let a = root.SomeProperty
Run Code Online (Sandbox Code Playgroud)
我收到错误:
错误:类型提供程序'typeproviders.providerpoc + MyProvider'在提供的类型'typeproviders.providerpoc.Provided.Root',成员'get_Menu'的上下文中报告错误.
错误:将表达式拼接到引号文字时键入不匹配.
插入的表达式树的类型与拼接操作所期望的类型不匹配.
预期'System.Object',但收到类型'System.String'.
考虑使用预期的表达式类型进行类型注释,例如(%% x:string)或(%x:string)..参数名称:receivedType.
如何编写报价以便能够在报价单内调用函数?
谢谢!
错误消息的含义是您将一个带引号的表达式放在需要引用表达式的obj地方string.
我怀疑GetterCode在提供的属性中创建时会发生这种情况:
GetterCode = (fun args -> <@@ f %%(args.[0]) @@>)
Run Code Online (Sandbox Code Playgroud)
这里args是一个带引号的表达式数组,其中每个表达式都是类型obj,但函数f需要一个字符串,因此填充空洞的引用%%应该是类型string
添加一个类型转换,将转obj成string应该做的伎俩:
GetterCode = (fun args -> <@@ f (unbox<string> (%%(args.[0]))) @@>)
Run Code Online (Sandbox Code Playgroud)