我该如何让以下内容生效?
我需要编写一个函数,它可以接受一个 Expr 列表,并返回一个 Expr (Expr 列表-> Epxr)。
我创建了DataObject类型来添加args的值。但是我无法管理代码迭代通过不同的args(args.[0]..args.[i])。我得到的消息是:
“变量“arg”在引用中被绑定,但被用作一个加入表达式的一部分。这是不允许的,因为它可能逃脱其范围。”
如果我明确访问args(args.[0],args.[1],...),解决方案就可以工作,但只要我尝试添加迭代,我就会遇到问题。由于args列表的长度是灵活的,所以对我来说这不是可行的解决方案。
我尝试了不同的方法,但都没有成功。有什么解决办法吗?
【编辑】
将Tomas的反馈添加到我的解决方案中,我得到了这个结果:
我需要编写一个函数,它可以接受一个 Expr 列表,并返回一个 Expr (Expr 列表-> Epxr)。
type DataObject() =
let data = System.Collections.Generic.Dictionary<int, obj>()
member this.AddValue propertyIndex value = data.Add(propertyIndex, value)
member this.GetValue propertyIndex =
match data.TryGetValue propertyIndex with
| (true, value) -> value
| (false, _) -> box "property not found"
...
(fun args ->
<@@
let data = new DataObject(values)
args |> List.iteri (fun i arg -> data.AddValue i <@@ (%%arg) : string @@>)
data
@@>)
我创建了DataObject类型来添加args的值。但是我无法管理代码迭代通过不同的args(args.[0]..args.[i])。我得到的消息是:
“变量“arg”在引用中被绑定,但被用作一个加入表达式的一部分。这是不允许的,因为它可能逃脱其范围。”
如果我明确访问args(args.[0],args.[1],...),解决方案就可以工作,但只要我尝试添加迭代,我就会遇到问题。由于args列表的长度是灵活的,所以对我来说这不是可行的解决方案。
我尝试了不同的方法,但都没有成功。有什么解决办法吗?
【编辑】
将Tomas的反馈添加到我的解决方案中,我得到了这个结果:
type DataObject(values: obj []) =
let propertyMap = new Map<int, obj>(values |> Seq.mapi (fun i value -> (i, value)))
member this.GetValue propertyIndex : obj =
match propertyMap.TryFind propertyIndex with
| Some(value) -> value
| None -> box "property not found"
(fun args ->
let boxedArgs =
args |> List.map (fun arg ->
match arg with
| Quotations.Patterns.Var var ->
if var.Type = typeof<int> then
<@@ (box (%%arg: int)) @@>
else if var.Type = typeof<string> then
<@@ (box (%%arg: string)) @@>
else if var.Type = typeof<System.Guid> then
<@@ (box (%%arg: System.Guid)) @@>
else
failwith ("Aha: " + var.Type.ToString())
| _ -> failwith ("Unknown Expr as parameter"))
<@@ new DataObject(%%(Expr.NewArray(typeof<obj>, boxedArgs))) @@>))
这很有效!唯一的问题是我想摆脱if...else结构来得到正确的转换。有什么想法吗?
Expr.Coerce(arg, typeof<obj>)
替换if
- 这应该会给你一个表示任何其他表达式arg
装箱的表达式。 - Tomas Petricek