Übergeben Sie den Funktionsparameter erster Klasse an den LINQ-Ausdruck

Bent Tranberg

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.

Asphalt

Hier gibt es also zwei Fragen.

Wie übergebe ich eine Funktion, ohne sie einpacken zu müssen <@ ... @>?

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))

Wie konvertiere ich von 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.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

Übergeben Sie den Funktionsparameter an eine andere Funktion

Übergeben Sie den Funktionsparameter direkt an die Klassenvariable

Übergeben Sie den Systemnamen als Funktionsparameter

Übergeben Sie den Ausdruck an den Initialisierer

Übergeben Sie den Ausdruck als benannten Argumentnamen

Übergeben Sie den bedingten Ausdruck als Funktionsargument

Reflektieren Sie die Struktur, die an den Funktionsparameter interface {} übergeben wurde

Übergeben Sie den Funktionsparameter, ohne die Funktion aufzurufen

So übergeben Sie den Indexwert an den Ausdruck * ngIf

Übergeben Sie den Datentyp der Klasse

Übergeben Sie den Frame an eine andere Klasse

Negieren Sie den LINQ-Ausdruck `.Where ()`

So übergeben Sie eine Klasse als Funktionsparameter

Übergeben Sie den Zeiger an 2D VLA als Funktionsparameter, der den Zeilenvektor in C füllt

So beheben Sie den Fehler: Konstanter Ausdruck erwartet, wenn versucht wird, Daten an eine benutzerdefinierte Klasse in Flutter / Dart zu übergeben

Lenker: Übergeben Sie den Index von jedem an einen verschachtelten Ausdruck

Winkel: Bewerten Sie den Ausdruck, der an das Komponentenattribut übergeben wird

Übergeben Sie den Ausdruck als Variable an die Kurve

Übergeben Sie den Ausdrucksparameter als Argument an einen anderen Ausdruck

Übergeben Sie einen Parameter an den wiederverwendbaren Ausdruck in einem Entity Framework

Analysieren Sie den Funktionsparameter in bash und übergeben Sie ihn an eine neue Funktion

Verwenden Sie den Ausdruck als ng-Klasse in eckigen js

Konvertieren Sie den Lambda-Ausdruck in eine umschlossene Klasse

Übergeben Sie den Benutzer mit React Router Dom an die Klasse

Deklarieren Sie den Klassentyp mit TypeScript (Klasse als Parameter übergeben)

Übergeben Sie den ID-Parameter an die importierte Klasse in Django

Übergeben Sie den Pandas-Datenrahmen an die Klasse

So übergeben Sie den generischen C # -Typ an eine andere Klasse

Übergeben Sie die Klasse an den Host der untergeordneten Komponente

TOP Liste

  1. 1

    So legen Sie mit dem Interface Builder unterschiedliche führende Speicherplätze für unterschiedliche Geräte fest

  2. 2

    Fügen Sie eine weitere Schaltfläche zu gwt Suggest Box hinzu

  3. 3

    Wie konvertiere ich einen Vektor von Bytes (u8) in eine Zeichenfolge?

  4. 4

    Wie kann ich in SCSS mehrere Klassen zu einer einzigen kombinieren?

  5. 5

    Wie konvertiert man einen Datenrahmen im langen Format in eine Liste mit einem geeigneten Format?

  6. 6

    Speichern Sie ein MPAndroidChart-Diagramm in einem Bild, ohne es in einer Aktivität anzuzeigen

  7. 7

    Gruppieren Sie Datenrahmenspalten nach ihrem Datum (die Spaltentitel enthalten) und fassen Sie die Instanzen von Einsen und Nullen in R . zusammen

  8. 8

    Tomcat - Leiten Sie den alten Kontextstamm zum neuen Kontextstamm um

  9. 9

    Eclipse Oxygen - Projekte verschwinden

  10. 10

    Wie wählt man Unterschiede mit drei Tabellen aus?

  11. 11

    Tic Tac Toe-Spiel im React-Reset-Button funktioniert nicht

  12. 12

    So berechnen Sie die Verfügbarkeit von Anwendungen (SLA)

  13. 13

    ElasticSearch BulkShardRequest ist aufgrund von org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor fehlgeschlagen

  14. 14

    Wie kann ich den Kaskadenmodus global einstellen?

  15. 15

    Python: Spalten mit demselben Namen zusammenführen, wobei der Mindestwert beibehalten wird

  16. 16

    So erhalten Sie eine gleichmäßige Höhe für alle Eingabefelder

  17. 17

    Wie erstelle ich einen neuen übergeordneten Knoten außerhalb der .ref (/ path) in der Firebase-Echtzeitdatenbank mithilfe von Cloud-Funktionen (Typescript)?

  18. 18

    Was ist schneller: SUM über NULL oder über 0?

  19. 19

    Wie kann ich eine verschachtelte Schleife mit lapply in R ersetzen?

  20. 20

    Kann ich ein Tkinter-Canvas erstellen, das mehrere Zeilen in einem Text-Widget umfasst?

  21. 21

    Ärgerliches Problem mit yaml, das ich nicht lösen kann

heißlabel

Archiv