의 우리가 간단한 F 번호 인용 있다고 가정 해 봅시다 :생성 매개 변수 F 번호 견적
type Pet = { Name : string } let exprNonGeneric = <@@ System.Func(fun (x : Pet) -> x.Name) @@>
결과 인용은 같은 것입니다 :
val exprNonGeneri : Expr = NewDelegate (System.Func`2[[FSI_0152+Pet, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], x, PropertyGet (Some (x), System.String Name, []))
지금 나는 그것을 일반화 할를, 그래서 대신 유형의 I "애완 동물 "속성 및"Name "속성에 정의 된 임의의 형식 및 메서드/속성을 사용할 수 있습니다. 여기에 내가 할 노력하고 무엇 :
let exprGeneric<'T, 'R> f = <@@ System.Func<'T, 'R>(%f) @@> let exprSpecialized = exprGeneric<Pet, string> <@ (fun (x : Pet) -> x.Name) @>
결과 표현은 이제 다른 : 당신이 볼 수 있듯이
val exprSpecialized : Expr = NewDelegate (System.Func`2[[FSI_0152+Pet, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], delegateArg, Application (Lambda (x, PropertyGet (Some (x), System.String Name, [])), delegateArg))
, 제 1 및 제 2 표현의 차이는 첫 번째 경우에 최상위 NewDelegate 표현식은 PropertyGet을 포함하고, 두 번째 표현식은 PropertyGet을 Application/Lambda 표현식으로 둘러 쌉니다. 그리고이 표현식을 외부 코드에 전달할 때 그러한 표현 구조를 기대하지 않고 실패합니다.
일반화 된 버전의 견적을 작성하려면 어떤 방법이 필요하므로 특수화되면 결과 인용 부호는 < @@ System.Func (fun (x : Pet) -> x.Name)과 정확하게 일치합니다. @@ >. 이것이 가능한가? 또는 생성 된 견적에 패턴 매칭을 수동으로 적용하고 필요한대로 변환 할 수있는 유일한 선택입니까?
업데이트. 해결 방법으로 다음 어댑터를 구현했습니다.
let convertExpr (expr : Expr) = match expr with | NewDelegate(t, darg, appl) -> match (darg, appl) with | (delegateArg, appl) -> match appl with | Application(l, ldarg) -> match (l, ldarg) with | (Lambda(x, f), delegateArg) -> Expr.NewDelegate(t, [x], f) | _ -> expr | _ -> expr | _ -> expr
이제는 표현식을 1에서 2로 변환 할 수 있습니다. 그러나 표현 트리를 가로 지르지 않고 간단한 방법으로 달성 할 수 있는지 알아 보는 데 관심이 있습니다.
답변 해 주신 점 감사드립니다. 그러나 여전히 관련 문제가 있습니다. 간단한 F # 대리인 (예 : fun x -> x.Name)을 위에 인용 된 # 2와 같은 실제 유형과 무관 한 일반 인용에 연결할 수 있습니까? 이는 조롱 프레임 워크가하는 것과 유사합니다. 즉, 구체적인 인터페이스를 모르고 구체적인 유형을 주입하지 않고 일부 표현식을 정의합니다. 나는 F #에서 이것을 달성 할 수 없을 것 같습니다. –
@Vagif - 귀하의 질문을 이해할 수 있는지 잘 모르겠습니다. 당신이하려는 일에 대해 좀 더 자세히 설명해 주시겠습니까? – kvb
F #과 C# 사이에 interop을 보내야합니다. C#은 특정 종류의 LINQ 표현식을 기대합니다. F #으로 하드 코딩 된 방식으로 작성할 수 있지만 이에 대한 일반 F # 래퍼를 작성하려고합니다. 이 래퍼는 "fun x -> x.Name"과 같은 입력 람다를 가져 와서 인용으로 변환 할 수 있어야합니다. 나는 이것이 일반적인 경우에는 불가능하다고 생각하기 시작했다. –