C # Truyền Lambda Expression làm Tham số Phương thức


105

Tôi có một biểu thức lambda mà tôi muốn có thể chuyển qua và sử dụng lại. Đây là mã:

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

Chìa khóa ở đây là tôi muốn có thể chuyển biểu thức lambda mà tôi đang sử dụng ở đây vào phương thức đang gọi mã này, để tôi có thể sử dụng lại nó. Biểu thức lambda là đối số thứ hai bên trong phương thức .Query của tôi. Tôi cho rằng tôi muốn sử dụng một Hành động hoặc Hàm, nhưng tôi không chắc cú pháp của nó là gì hoặc nó hoạt động như thế nào. Ai đó có thể vui lòng cho tôi một ví dụ?


3
Đặt tham số thành Hành động hoặc Chức năng.
Metro Smurf

Đúng vậy, đó là những gì tôi nghĩ ... bạn có thể cho tôi một ví dụ về cách tôi sẽ làm điều này?
Adam Levitt

Câu trả lời:


122

Sử dụng một Func<T1, T2, TResult>đại biểu làm kiểu tham số và chuyển nó vào 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>();   
  }  
}

Bạn sẽ gọi nó là:

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

Hoặc gán lambda cho một biến và chuyển vào.


Điều này trông rất tốt, và làm cách nào để xác định lambda NGOÀI của phương thức getJobs này? Nói cách khác, dòng trước lệnh gọi getJobs () trông như thế nào để xác định lambda?
Adam Levitt

@AdamLevitt - Theo cách bạn làm với mã mẫu của mình. Sẽ thêm để trả lời.
Đưa vào

Ngoài ra, các tham số chức năng có thể là động không?
Adam Levitt

@AdamLevitt - bạn có thể làm cho hàm chung chung, mặc dù nếu bạn muốn số lượng tham số khác nhau trên lambdas, bạn sẽ cần quá tải.
Oded

Đúng. Những gì tôi thực sự muốn là có thể chuyển các triển khai khác nhau của giao diện IJob, nhưng điều đó sẽ không hoạt động với Truy vấn của Dapper <> vì nó yêu cầu lớp cấy ghép chung chung thực tế tại thời gian chạy. Điều này vẫn còn khá gần với những gì tôi đã hy vọng.
Adam Levitt

27

Nếu tôi hiểu bạn cần mã sau. (truyền biểu thức lambda theo tham số)

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
    }

Phương thức gọi điện

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

Bạn có thể làm điều tương tự trong lớp học của họ, hãy xem đây là ví dụ.

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

Phương thức gọi điện

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

Tôi hy vọng điều này hữu ích


2
Bạn có thể giải thích lý do tại sao chúng tôi cần Compile()trong .Where? Tôi đã thấy nó hoạt động mà không có điều đó quá.
Sнаđошƒаӽ

7

Biểu thức Lambda có kiểu Action<parameters>(trong trường hợp chúng không trả về giá trị) hoặc Func<parameters,return>(trong trường hợp chúng có giá trị trả về). Trong trường hợp của bạn, bạn có hai tham số đầu vào và bạn cần trả về một giá trị, vì vậy bạn nên sử dụng:

Func<FullTimeJob, Student, FullTimeJob>

5

Bạn nên sử dụng kiểu đại biểu và chỉ định đó làm tham số lệnh của bạn. Bạn có thể sử dụng một trong các kiểu ủy quyền tích hợp sẵn - ActionFunc.

Trong trường hợp của bạn, có vẻ như đại biểu của bạn nhận hai tham số và trả về một kết quả, vì vậy bạn có thể sử dụng Func:

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

Sau đó bạn có thể gọi GetJobs phương thức truyền trong một cá thể ủy quyền. Đây có thể là một phương thức khớp với chữ ký đó, một đại biểu ẩn danh hoặc một biểu thức lambda.

PS Bạn nên sử dụng PascalCase cho tên phương thức - GetJobs, không phải getJobs.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.