Ngôn ngữ LINQ - Toán tử Expression
Expression trong LINQ
Chúng ta đã tìm hiểu về Biểu thức lambda có thể gán cho kiểu delegate Func hoặc delegate Action để xử lý các tập hợp trong bộ nhớ. Trình biên dịch .NET sẽ chuyển đổi biểu thức lambda được gán cho delegate Func hoặc delegate Action thành mã thực thi tại thời điểm biên dịch.
Expression trong LINQ
LINQ đã giới thiệu kiểu dữ liệu mới có tên là Expression (biểu thức) đại diện cho biểu thức lambda được định kiểu mạnh. Nó có nghĩa là biểu thức lambda cũng có thể được gán cho kiểu Expression<TDelegate>
.
Trình biên dịch .NET chuyển đổi biểu thức lambda được gán cho Expression<TDelegate> thành cây biểu thức thay vì mã thực thi.
Cây biểu thức (expression tree) này được các trình cung cấp truy vấn LINQ từ xa (remote LINQ query providers) sử dụng làm cấu trúc dữ liệu để xây dựng một truy vấn lúc thực thi từ nó (như LINQ-to-SQL, EntityFramework hoặc bất kỳ trình cung cấp truy vấn LINQ nào khác triển khai interface IQueryable<T>).
Hình dưới đây minh họa sự khác biệt khi biểu thức lambda được gán cho delegate Func hoặc delegate Action và Expression trong LINQ.
Chúng ta sẽ tìm hiểu cây biểu thức trong phần tiếp theo, nhưng trước tiên, hãy xem cách định nghĩa và gọi Expression.
Định nghĩa một Expression
Sử dụng namespace System.Linq.Expressions và lớp Expression<TDelegate>
để định nghĩa một Expression. Expression<TDelegate> yêu cầu kiểu delegate Func hoặc Action.
Ví dụ: bạn có thể gán biểu thức lambda cho biến isTeenAger của delegate Func, như được trình bày bên dưới:
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
}
Func<Student, bool> isTeenAger = s => s.Age > 12 && s.Age < 20;
Và bây giờ, bạn có thể chuyển đổi delegate Func ở trên thành Expression bằng cách khai báo như sau:
Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20;
Cũng theo cách tương tự, bạn cũng có thể chuyển đổi delegate Action thành Expression bằng cách khai báo như sau
Expression<Action<Student>> printStudentName = s => Console.WriteLine(s.StudentName);
Như vậy là bạn đã biết cách định nghĩa một biểu thức Expression<TDelegate>. Bây giờ, hãy xem cách gọi một biểu thức Expression<TDelegate>.
Gọi một Expression
Bạn có thể gọi một biểu thức Expression giống như cách gọi một delegate, nhưng trước tiên bạn cần biên dịch nó bằng phương thức Compile()
.
Phương thức Compile trả về kiểu delegate Func hoặc delegate Action để bạn có thể gọi nó như một delegate. Ví dụ sau minh họa gọi một biểu thức Expression:
Expression<Func<Student, bool>> isTeenAgerExpr = s => s.Age > 12 && s.Age < 20;
//compile Expression using Compile method to invoke it as Delegate
Func<Student, bool> isTeenAger = isTeenAgerExpr.Compile();
//Invoke
bool result = isTeenAger(new Student(){ StudentID = 1, StudentName = "Steve", Age = 20});