In this post let’s see how we can access nested properties in Expression Trees. In one of my previous posts, I wrote about Writing a Very Basic Dynamic Query using Expression Trees. There I wrote a expression tree which accesses the first level properties of a class. And today I am going to write a expression tree which accesses the nested properties of a class.
Let’s consider the following scenario. I have two classes named “Employee” and “Department”. Employee is belonging to a department. I can model the relationship as follows.
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public virtual Department Department { get; set; }
public static List<Employee> GetEmployees()
{
return new List<Employee>()
{
new Employee()
{
EmployeeId=1,
Name="Jaliya Udagedara",
Department = Department.GetDepartments().First(d=>d.DepartmentId==1)
},
new Employee()
{
EmployeeId=1,
Name="John Smith",
Department = Department.GetDepartments().First(d=>d.DepartmentId==2)
},
new Employee()
{
EmployeeId=1,
Name="Jane Smith",
Department = Department.GetDepartments().First(d=>d.DepartmentId==1)
}
};
}
}
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
public static List<Department> GetDepartments()
{
return new List<Department>()
{
new Department(){DepartmentId=1,Name="Microsoft Visual Studio"},
new Department(){DepartmentId=2,Name="Microsoft SQL Server"}
};
}
}
IEnumerable<Employee> employees = Employee.GetEmployees().Where(e => e.Department.DepartmentId == 1);
First step is to create the expression tree that represents the parameter to the predicate which is “e”.
ParameterExpression pe = Expression.Parameter(typeof(Employee), "e");
Expression left = Expression.Property(pe, typeof(Employee).GetProperty("Department"));
left = Expression.Property(left, typeof(Department).GetProperty("DepartmentId"));
In above two lines, first line is for accessing the Department property of the Employee. Then in the second line I am accessing the property DepartmentId and note that what I have passed as the first parameter of Expression.Property() method. It’s the Department property of the Employee. So what means here is I am accessing the DepartmentId property of the Department. Now you must be getting how it works, by following the above approach, we can access any property in any level.
Then it’s pretty much a simple task ahead. We have to compose the right side of the expression, compile the expression tree into executable code and finally pass it to Where extension method. For that I am writing the following.
Expression right = Expression.Constant(1, typeof(int));
Expression expression = Expression.Equal(left, right);
var lambda = Expression.Lambda<Func<Employee, bool>>(expression, pe).Compile();
IEnumerable<Employee> employees = Employee.GetEmployees().Where(lambda);
ParameterExpression pe = Expression.Parameter(typeof(Employee), "e");
Expression left = Expression.Property(pe, typeof(Employee).GetProperty("Department"));
left = Expression.Property(left, typeof(Department).GetProperty("DepartmentId"));
Expression right = Expression.Constant(1, typeof(int));
Expression expression = Expression.Equal(left, right);
var lambda = Expression.Lambda<Func<Employee, bool>>(expression, pe).Compile();
IEnumerable<Employee> employees = Employee.GetEmployees().Where(lambda);
And this is the output when I foreach on “employees”.
Result |
Happy Coding.
Regards,
Jaliya
What if nested property is List of any entity.
ReplyDeleteEx- x=>x.ABCs.FirstOrDefault().Name