F# - 重建表达式树

时间:2011-04-25 19:13:09

标签: f#

好吧......这个问题或多或少与我今天早些时候提出的问题有关(F# - "Not a valid property expression"),@ Tomas Petricek完全回答 - 但是看来我缺乏知识和DLR,需要我再问一次(一直试着将一些东西搞砸而没有运气)。

我正在使用此功能(从前一个帖子中Tomas给出的示例中窃取):

let hasSeq (e:Expr<'a -> seq<'b>>) =
  match e with
  | Patterns.Lambda(v, Patterns.PropertyGet(Some instance, propInfo, [])) ->
      printfn "Get property %s of %A" propInfo.Name instance
      // TODO: Use 'Expr.Lambda' & 'Expr.PropGet' to construct
      // an expression tree in the expected format
  | _ -> failwith "Not a lambda!"

如何使用Expr.LambdaExpr.PropGet重建表达式树? - 我需要改为seq<'b>ICollection<'b>,以便最后的表达式如下:'a -> ICollection<'b>

2 个答案:

答案 0 :(得分:3)

好吧,如果您已经分解了引用,那么也许您可以自己创建所需的表达式树,而不需要PowerPack中的ToLinqExpression

type A = 
    member this.Values : int[] = failwith "" 

open Microsoft.FSharp.Quotations

type F<'T, 'R> = System.Func<'T, 'R>
type E = System.Linq.Expressions.Expression
type IC<'T> = System.Collections.Generic.ICollection<'T> 

let toLinqPropGet (e : Expr<'T -> #seq<'R>>) = 
    match e with
    | Patterns.Lambda(_, Patterns.PropertyGet(Some _, pi, [])) 
          when typeof<IC<'R>>.IsAssignableFrom(pi.PropertyType) ->
        let p = E.Parameter(typeof<'T>)
        let propGet = E.Property(p :> E, pi)
        E.Lambda<F<'T, IC<'R>>>(propGet, p) :> E
    | _ -> failwith "PropGet expected"

let r = toLinqPropGet <@ fun (x : A) -> x.Values @>        
printfn "%A" r    

答案 1 :(得分:1)

这不起作用。

您希望构建类型为Entity -> ICollection<Something>的引号,并且引用类型为Entity -> seq<Something>的引号。但是,实体框架仅支持获取某些属性的简单lambda函数(例如x => x.SomeProperty)。

如果您的Entity只有Foo类型的属性seq<Something>,则无法构建具有所需结构的引用(仅获取属性的lambda)和所需类型(Entity -> ICollection<Something>),因为属性的类型不匹配!

我之前建议的是将实体更改为具有正确类型(FooInternal)的属性ICollection<Something>。然后你可以构建一个引用x => x.FooInternal,它可以与实体框架一起使用。

也许您可以提供有关您实际尝试实现的内容的更多详细信息?我们可以尝试帮助提供技术细节,但似乎您可能需要稍微调整一下您的设计(以实际使用EF所要求的ICollection类型)。