C # Passer une expression Lambda comme paramètre de méthode

106

J'ai une expression lambda que j'aimerais pouvoir faire circuler et réutiliser. Voici le code:

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 clé ici, c'est que je veux pouvoir passer l'expression lambda que j'utilise ici dans la méthode qui appelle ce code, afin que je puisse le réutiliser. L'expression lambda est le deuxième argument de ma méthode .Query. Je suppose que je voudrais utiliser une Action ou une Func, mais je ne suis pas tout à fait sûr de la syntaxe de ceci ou de son fonctionnement. Quelqu'un peut-il me donner un exemple?

Adam Levitt
la source
3
Faites du paramètre une Action ou une Func.
Metro Schtroumpf
C'est ce que je pensais ... pouvez-vous me montrer un exemple de la façon dont je ferais ça?
Adam Levitt
duplication possible d' expressions lambda C # comme arguments de fonction
utilisateur

Réponses:

123

Utilisez un Func<T1, T2, TResult>délégué comme type de paramètre et transmettez-le à votre 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>();   
  }  
}

Vous l'appeleriez:

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

Ou affectez le lambda à une variable et passez- le .

Oded
la source
Cela semble très bien, et comment définirais-je le lambda À L'EXTÉRIEUR de cette méthode getJobs? En d'autres termes, à quoi ressemble la ligne avant l'appel à getJobs () pour définir le lambda?
Adam Levitt
@AdamLevitt - De la même manière que vous avez avec votre exemple de code. Ajoutera à la réponse.
Oded
En outre, les paramètres de fonction peuvent-ils être dynamiques de toute façon?
Adam Levitt
@AdamLevitt - vous pouvez rendre la fonction générique, mais si vous voulez des nombres différents de paramètres sur les lambdas, vous aurez besoin de surcharges.
Oded le
Droite. Ce que j'aimerais en fait, c'est pouvoir transmettre différentes implémentations de l'interface IJob, mais cela ne fonctionnera pas avec Dapper's Query <> car il nécessite la classe impl générique réelle au moment de l'exécution. C'est encore assez proche de ce que j'espérais.
Adam Levitt
27

Si je comprends bien, vous avez besoin du code suivant. (en passant l'expression lambda par paramètre) La méthode

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
    }

Méthode d'appel

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

Vous pouvez faire la même chose dans leur classe, voir cet exemple.

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;
    }

Méthode d'appel

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

J'espère que c'est utile

Marinpietri
la source
2
Pouvez-vous expliquer pourquoi nous avons besoin du Compile()dans le .Where? J'ai vu que cela fonctionne sans cela aussi.
Sнаđошƒаӽ
7

Les expressions Lambda ont un type de Action<parameters>(au cas où elles ne renverraient pas de valeur) ou Func<parameters,return>(au cas où elles auraient une valeur de retour). Dans votre cas, vous avez deux paramètres d'entrée et vous devez renvoyer une valeur, vous devez donc utiliser:

Func<FullTimeJob, Student, FullTimeJob>
SztupY
la source
5

Vous devez utiliser un type de délégué et le spécifier comme paramètre de commande. Vous pouvez utiliser l'un des types de délégués intégrés - Actionet Func.

Dans votre cas, il semble que votre délégué prenne deux paramètres et renvoie un résultat, vous pouvez donc utiliser Func:

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

Vous pouvez ensuite appeler votre GetJobsméthode en passant une instance de délégué. Cela peut être une méthode qui correspond à cette signature, un délégué anonyme ou une expression lambda.

PS Vous devriez utiliser PascalCase pour les noms de méthode - GetJobs, pas getJobs.

devdigital
la source