C # Passa l'espressione Lambda come parametro del metodo


106

Ho un'espressione lambda che vorrei poter trasmettere e riutilizzare. Ecco il codice:

public List<IJob> getJobs(/* i want to pass the lambda expr in here */) {
  using (SqlConnection connection = new SqlConnection(getConnectionString())) {
    connection.Open();
    return connection.Query<FullTimeJob, Student, FullTimeJob>(sql, 
      (job, student) => {         
        job.Student = student;
        job.StudentId = student.Id;
        return job;
        },
        splitOn: "user_id",
        param: parameters).ToList<IJob>();   
  }   

La chiave qui è che voglio essere in grado di passare l'espressione lambda che sto usando qui nel metodo che chiama questo codice, in modo da poterlo riutilizzare. L'espressione lambda è il secondo argomento all'interno del mio metodo .Query. Presumo che vorrei utilizzare un'azione o una funzione, ma non sono abbastanza sicuro di quale sia la sintassi per questo o di come funzioni. Qualcuno può darmi un esempio?


3
Rendi il parametro un'azione o una funzione.
Metro Smurf

Bene, è quello che pensavo ... puoi mostrarmi un esempio di come lo farei?
Adam Levitt

Risposte:


123

Usa un Func<T1, T2, TResult>delegato come tipo di parametro e passalo al tuo Query:

public List<IJob> getJobs(Func<FullTimeJob, Student, FullTimeJob> lambda)
{
  using (SqlConnection connection = new SqlConnection(getConnectionString())) {
    connection.Open();
    return connection.Query<FullTimeJob, Student, FullTimeJob>(sql, 
        lambda,
        splitOn: "user_id",
        param: parameters).ToList<IJob>();   
  }  
}

Lo chiameresti:

getJobs((job, student) => {         
        job.Student = student;
        job.StudentId = student.Id;
        return job;
        });

O assegnare il lambda a una variabile e passare esso in.


Sembra molto buono e come definirei il lambda ESTERNO di questo metodo getJobs? In altre parole, qual è la riga prima della chiamata a getJobs () per definire lambda?
Adam Levitt

@AdamLevitt - Allo stesso modo che hai con il tuo codice di esempio. Aggiungerò alla risposta.
Oded

Inoltre, i parametri della funzione possono essere comunque dinamici?
Adam Levitt

@AdamLevitt - puoi rendere la funzione generica, anche se se vuoi un numero diverso di parametri sui lambda, avrai bisogno di sovraccarichi.
Oded

Destra. Quello che mi piacerebbe in realtà è essere in grado di passare in diverse implementazioni dell'interfaccia IJob, ma questo non funzionerà con Dapper's Query <> perché richiede la classe impl generica effettiva in fase di esecuzione. Questo è ancora abbastanza vicino a quello che speravo.
Adam Levitt

27

Se ho capito hai bisogno del seguente codice. (passando l'espressione lambda per parametro) Il metodo

public static void Method(Expression<Func<int, bool>> predicate) { 
    int[] number={1,2,3,4,5,6,7,8,9,10};
    var newList = from x in number
                  .Where(predicate.Compile()) //here compile your clausuly
                  select x;
                newList.ToList();//return a new list
    }

Metodo di chiamata

Method(v => v.Equals(1));

Puoi fare lo stesso nella loro classe, vedi questo è un esempio.

public string Name {get;set;}

public static List<Class> GetList(Expression<Func<Class, bool>> predicate)
    {
        List<Class> c = new List<Class>();
        c.Add(new Class("name1"));
        c.Add(new Class("name2"));

        var f = from g in c.
                Where (predicate.Compile())
                select g;
        f.ToList();

       return f;
    }

Metodo di chiamata

Class.GetList(c=>c.Name=="yourname");

Spero sia utile


2
Puoi spiegare perché abbiamo bisogno di Compile()in .Where? Ho visto che funziona anche senza quello.
Sнаđошƒаӽ

7

Le espressioni lambda hanno un tipo di Action<parameters>(nel caso in cui non restituiscano un valore) o Func<parameters,return>(nel caso in cui abbiano un valore di ritorno). Nel tuo caso hai due parametri di input e devi restituire un valore, quindi dovresti usare:

Func<FullTimeJob, Student, FullTimeJob>

5

È necessario utilizzare un tipo di delegato e specificarlo come parametro di comando. È possibile utilizzare uno dei tipi di delegati incorporati ActioneFunc .

Nel tuo caso, sembra che il tuo delegato prenda due parametri e restituisca un risultato, quindi potresti usare Func:

List<IJob> GetJobs(Func<FullTimeJob, Student, FullTimeJob> projection)

Potresti quindi chiamare il tuo GetJobs metodo passando in un'istanza del delegato. Potrebbe essere un metodo che corrisponde a quella firma, un delegato anonimo o un'espressione lambda.

PS Dovresti usare PascalCase per i nomi dei metodi - GetJobs, non getJobs.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.