Une façon vous pouvez faire est de tirer profit du fait que F # effectuera cette conversion automatiquement lors de l'appel des méthodes sur les types .NET qui attendent une Expression<Func<...>>
. Je ne suis pas tout à fait sûr quand cela a été ajouté à la langue, mais certainement avec F # 4, vous n'avez pas besoin de convertir explicitement les expressions F # en celles de LINQ. Si la raison pour laquelle vous vouliez faire en premier lieu devait être en mesure d'utiliser IQueryable
API LINQ (ou d'autres API .NET basées sur des expressions) alors maintenant fonctionne sans effort, par exemple:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
juste travaux. Même si cela ressemble à un lambda ordinaire (nous n'avons pas utilisé la syntaxe d'expression de F #), cela compile en un code qui produit un objet d'expression F #, puis le passe à LeafExpressionConverter.QuotationToExpression
pour le transformer en objet d'expression LINQ.
Mais parfois, vous voudrez obtenir l'objet d'expression de style LINQ directement dans F #. (Par exemple, il est parfois utile d'écrire une fonction F # qui produit une expression que vous utiliserez dans plusieurs requêtes.) Dans ce cas, vous pouvez écrire un aide comme ceci:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
Cela ressemble il ne fait rien - il retourne juste son argument. Cependant, étant donné que FunAs
est un type .NET, F # compilera automatiquement tout site d'appel qui l'appelle avec une expression fun
en code qui génère une expression de requête LINQ appropriée. .: par exemple
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
Ici, linqExpr
sera de type Expression<Func<MyEntity, bool>>
.
La clé de cette méthode est que cette méthode est membre d'un type .NET. Si vous essayez exactement la même chose avec une fonction F # ordinaire:
let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
qui semble que cela devrait vouloir dire exactement la même chose que FunAs.LinqExpression
, vous constaterez que vous ne pouvez pas appeler de la même manière. Par exemple, si vous essayez ceci:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
Vous obtiendrez une (un peu inutile) Erreur: « Cette fonction prend trop d'arguments, ou est utilisé dans un contexte où une fonction n'expected`.En faisant de cette fonction un membre d'un type .NET, nous pouvons tirer parti de l'aide de F # "Vous semblez invoquer une API .NET qui attend une expression de style LINQ, laissez-moi m'en occuper" fonctionnalité.
(Il est possible qu'il y ait un peu plus explicite façon de demander au compilateur LINQ pour effectuer cette même astuce pour vous sans apporter un type .NET dans l'image, mais je l'ai pas trouvé.)
hey, a fait vous trouvez une manière plus simple de faire ceci? – nicolas
sur un sidenote, il ya une question connexe ici, (pas avec des citations cependant) http://stackoverflow.com/questions/3392000/interop-between-f-and-c-sharp-lambdas – nicolas