Dieses Code-Snippet gibt ein Problem wieder, das ich mit einem Produktionscode habe. Die Funktion enthält Eigenschaft repräsentiert eine reale Funktion, die sich tatsächlich in einer Bibliothek befindet, so dass ich kein Mitspracherecht bei der Signatur habe.
Das Problem ist, dass ich nicht herausfinden kann, wie eine Wrapper-Funktion erstellt wird, die eine normale Funktion als Argument verwenden kann, und diese dann an includesProperty weiterleitet. Ich kann includesProperty direkt mit einer Funktion als Lambda-Ausdruck aufrufen, aber ich kann sie nicht mit einer Funktion aufrufen, die aus einer anderen Quelle stammt.
Die Funktion addToGroup ist die beste, die ich bisher entwickelt habe, und verwendet Anführungszeichen. Bei diesem Ansatz gibt es zwei Probleme, die ich herauszufinden versuche. Wie entferne ich zuerst die Func-Besetzung im Zitat? Vielleicht irgendwie in addToGroup verschieben? Zweitens kann ich darauf aufbauen, um nur eine Funktion zu übergeben? Es ist mir nicht gelungen, etwas zu finden, das weder einen Kompilierungszeitfehler noch einen Laufzeitfehler erzeugt.
Die Funktion addToGroup2 ist das, was ich gerne machen würde, aber sie wird nicht kompiliert. Die Fehlermeldung lautet "Für den Typ 'Quotations.Expr <' a> 'sind keine Konstruktoren verfügbar".
Warum mache ich mir die Mühe, damit zu kämpfen? Denn solange ich die übergebene Funktion nicht als erstklassigen Wert behandeln kann, kann ich das gewünschte Design nicht erstellen. Ich möchte, dass diese Funktionen aus einer Sammlung von Datensätzen stammen.
Wenn Sie dieses Snippet in LINQPad oder etwas anderes einfügen, kommentieren Sie addToGroup2 und die Aufrufe dazu aus, damit das Snippet kompiliert und ausgeführt wird.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <@ Func<_,_>(fun x -> x.ConnectionString) @>
CfgSettingsMetadata.addToGroup <@ Func<_,_>(fun x -> x.Port) @>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Beide Antworten in Frage Expression <Func <T, bool >> von einer F # -Funktion haben mir etwas geholfen, aber ich habe noch keine Lösung gefunden.
Hier gibt es also zwei Fragen.
<@ ... @>
?Dazu müssen Sie nur das [<ReflectedDefinition>]
Attribut zum Parameter Ihrer Methode hinzufügen . Das ihm übergebene Argument wird implizit in ein Zitat eingeschlossen.
type CfgSettingsMetadata() =
static member addToGroup([<ReflectedDefinition>] f: Expr<CfgSettings -> 'TProperty>) =
CfgSettingsMetadata.containsProperty(LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(Func<_, _>(fun x -> x.ConnectionString))
Expr<a -> b>
nach Expression<Func<a, b>>
?Dies wird in der Tat in der von Ihnen verlinkten Frage erklärt, obwohl sich die API seitdem etwas geändert hat.
type CfgSettingsMetadata() =
static member addToGroup ([<ReflectedDefinition>] (f: Expr<CfgSettings -> 'TProperty>)) =
let call = LeafExpressionConverter.QuotationToExpression f :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
let e = Expression.Lambda<Func<CfgSettings, 'TProperty>>(lambda.Body, lambda.Parameters)
CfgSettingsMetadata.containsProperty(e) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(fun x -> x.ConnectionString)
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen