C # Pass Lambda Expression เป็นพารามิเตอร์วิธีการ


107

ฉันมีนิพจน์แลมบ์ดาที่ฉันต้องการจะส่งต่อและนำกลับมาใช้ใหม่ได้ นี่คือรหัส:

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

คีย์ตรงนี้คือฉันต้องการส่งนิพจน์แลมบ์ดาที่ฉันใช้ตรงนี้ไปยังเมธอดที่เรียกรหัสนี้เพื่อที่ฉันจะได้ใช้ซ้ำ นิพจน์แลมบ์ดาเป็นอาร์กิวเมนต์ที่สองภายในเมธอด. เคียวรีของฉัน ฉันสมมติว่าฉันต้องการใช้ Action หรือ Func แต่ฉันไม่ค่อยแน่ใจว่าไวยากรณ์นี้มีไว้เพื่ออะไรหรือทำงานอย่างไร ใครช่วยยกตัวอย่างหน่อยได้ไหม


3
ทำให้พารามิเตอร์เป็น Action หรือ Func
Metro Smurf

ใช่นั่นคือสิ่งที่ฉันคิด ... คุณช่วยดูตัวอย่างวิธีที่ฉันทำได้ไหม
Adam Levitt

คำตอบ:


124

ใช้Func<T1, T2, TResult>ผู้รับมอบสิทธิ์เป็นประเภทพารามิเตอร์และส่งต่อไปยัง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>();   
  }  
}

คุณจะเรียกมันว่า:

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

หรือมอบหมายแลมบ์ดาให้กับตัวแปรและผ่านมันใน


มันดูดีมากและฉันจะกำหนดแลมบ์ดาด้านนอกของเมธอด getJobs นี้ได้อย่างไร กล่าวอีกนัยหนึ่งบรรทัดก่อนการเรียก getJobs () มีลักษณะอย่างไรในการกำหนดแลมบ์ดา?
Adam Levitt

@AdamLevitt - แบบเดียวกับที่คุณมีโค้ดตัวอย่าง จะแอดมาตอบ.
Oded

นอกจากนี้พารามิเตอร์ของฟังก์ชันสามารถเป็นแบบไดนามิกได้หรือไม่
Adam Levitt

@AdamLevitt - คุณสามารถสร้างฟังก์ชั่นทั่วไปได้แม้ว่าคุณต้องการจำนวนพารามิเตอร์ที่แตกต่างกันบน lambdas คุณจะต้องมีการโอเวอร์โหลด
Oded

ขวา. สิ่งที่ฉันต้องการจริงๆคือสามารถส่งผ่านการใช้งานอินเทอร์เฟซ IJob ที่แตกต่างกันได้ แต่จะใช้ไม่ได้กับ Dapper's Query <> เนื่องจากต้องใช้คลาส im ทั่วไปจริงในขณะทำงาน นี่ยังคงค่อนข้างใกล้เคียงกับสิ่งที่ฉันหวังไว้
Adam Levitt

27

ถ้าฉันเข้าใจว่าคุณต้องการรหัสต่อไปนี้ (ส่งผ่านแลมบ์ดานิพจน์ตามพารามิเตอร์) วิธีการ

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
    }

วิธีการโทร

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

คุณสามารถทำเช่นเดียวกันในชั้นเรียนของพวกเขาดูนี่คือตัวอย่าง

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

วิธีการโทร

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

ฉันหวังว่านี่จะเป็นประโยชน์


2
คุณอธิบายได้ไหมว่าทำไมเราถึงต้องการสิ่งCompile()นี้.Where? ฉันเห็นว่ามันใช้งานได้โดยไม่ต้องใช้สิ่งนั้นด้วย
Sнаđошƒаӽ

7

นิพจน์ Lambda มีประเภทAction<parameters>(ในกรณีที่ไม่ส่งคืนค่า) หรือFunc<parameters,return>(ในกรณีที่มีค่าส่งคืน) ในกรณีของคุณคุณมีพารามิเตอร์อินพุตสองตัวและคุณต้องส่งคืนค่าดังนั้นคุณควรใช้:

Func<FullTimeJob, Student, FullTimeJob>

5

คุณควรใช้ชนิดผู้รับมอบสิทธิ์และระบุว่าเป็นพารามิเตอร์คำสั่งของคุณ คุณสามารถใช้หนึ่งในประเภทผู้รับมอบสิทธิ์ในตัว - ActionและFunc.

ในกรณีของคุณดูเหมือนว่าผู้รับมอบสิทธิ์ของคุณใช้พารามิเตอร์สองตัวและส่งคืนผลลัพธ์ดังนั้นคุณสามารถใช้Func:

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

จากนั้นคุณสามารถเรียกGetJobsเมธอดของคุณในอินสแตนซ์ผู้รับมอบสิทธิ์ นี่อาจเป็นวิธีการที่ตรงกับลายเซ็นนั้นผู้รับมอบสิทธิ์ที่ไม่ระบุชื่อหรือนิพจน์แลมบ์ดา

PS คุณควรใช้ PascalCase สำหรับชื่อวิธีการ - ไม่GetJobsgetJobs

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.