C # Lulus Ekspresi Lambda sebagai Parameter Metode

106

Saya memiliki ekspresi lambda yang ingin saya bagikan dan gunakan kembali. Berikut kodenya:

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

Kuncinya di sini, adalah saya ingin meneruskan ekspresi lambda yang saya gunakan di sini ke dalam metode yang memanggil kode ini, jadi saya bisa menggunakannya kembali. Ekspresi lambda adalah argumen kedua di dalam metode .Query saya. Saya berasumsi saya ingin menggunakan Action atau Func, tapi saya tidak begitu yakin apa sintaksnya atau bagaimana cara kerjanya. Bisakah seseorang memberi saya contoh?

Adam Levitt
sumber
3
Jadikan parameter sebagai Action atau Func.
Metro Smurf
Benar, itulah yang saya pikirkan ... dapatkah Anda menunjukkan kepada saya contoh bagaimana saya akan melakukan ini?
Adam Levitt
kemungkinan duplikat ekspresi C # lambda sebagai argumen fungsi
pengguna

Jawaban:

123

Gunakan Func<T1, T2, TResult>delegasi sebagai tipe parameter dan teruskan ke 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>();   
  }  
}

Anda akan menyebutnya:

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

Atau menetapkan lambda untuk variabel dan lulus itu di.

Oded
sumber
Ini terlihat sangat bagus, dan bagaimana saya mendefinisikan lambda DI LUAR metode getJobs ini? Dengan kata lain, seperti apa garis sebelum panggilan ke getJobs () untuk mendefinisikan lambda?
Adam Levitt
@AdamLevitt - Cara yang sama yang Anda lakukan dengan kode contoh Anda. Akan menambah jawaban.
Oded
Juga, dapatkah parameter fungsi menjadi dinamis?
Adam Levitt
@AdamLevitt - Anda dapat membuat fungsi menjadi generik, meskipun jika Anda menginginkan jumlah parameter yang berbeda pada lambda, Anda perlu kelebihan beban.
Oded
Baik. Apa yang sebenarnya saya inginkan adalah dapat meneruskan implementasi yang berbeda dari antarmuka IJob, tetapi itu tidak akan bekerja dengan Dapper's Query <> karena memerlukan kelas impl umum aktual pada waktu proses. Ini masih cukup dekat dengan apa yang saya harapkan.
Adam Levitt
27

Jika saya mengerti, Anda memerlukan kode berikut. (melewatkan ekspresi lambda dengan parameter) Metode

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
    }

Metode pemanggilan

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

Anda dapat melakukan hal yang sama di kelas mereka, lihat ini contohnya.

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

Metode pemanggilan

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

Semoga bermanfaat

Marinpietri
sumber
2
Bisakah Anda menjelaskan mengapa kami membutuhkan Compile()di .Where? Saya telah melihat itu berhasil tanpa itu juga.
Sнаđошƒаӽ
7

Ekspresi lambda memiliki tipe Action<parameters>(jika mereka tidak mengembalikan nilai) atau Func<parameters,return>(jika mereka memiliki nilai yang dikembalikan). Dalam kasus Anda, Anda memiliki dua parameter input, dan Anda perlu mengembalikan nilai, jadi Anda harus menggunakan:

Func<FullTimeJob, Student, FullTimeJob>
SztupY
sumber
5

Anda harus menggunakan tipe delegasi dan menetapkannya sebagai parameter perintah Anda. Anda dapat menggunakan salah satu tipe delegasi bawaan - Actiondan Func.

Dalam kasus Anda, sepertinya delegasi Anda mengambil dua parameter, dan mengembalikan hasil, sehingga Anda dapat menggunakan Func:

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

Anda kemudian dapat memanggil GetJobsmetode Anda dengan mengirimkan instance delegasi. Ini bisa menjadi metode yang cocok dengan tanda tangan itu, delegasi anonim, atau ekspresi lambda.

PS Anda harus menggunakan PascalCase untuk nama metode - GetJobs, bukan getJobs.

devdigital
sumber