Wednesday, August 6, 2014

Expression Trees - Accessing Nested Properties

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"}
        };
    }
}
Inside the classes I have two helper methods which will return me some data. Now let’s say I want to get all the employees who is working in department 1. I can write the following LINQ query.
IEnumerable<Employee> employees = Employee.GetEmployees().Where(e => e.Department.DepartmentId == 1);
Now how we can we write the same in using expression trees. Let’s find out.

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");
Now comes the place where we need to access the nested property.
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);
So following is how it look likes when all above parts comes together.
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”.
image
Result
I am uploading the sample to OneDrive, Enjoy!


Happy Coding.

Regards,
Jaliya

1 comment:

  1. What if nested property is List of any entity.
    Ex- x=>x.ABCs.FirstOrDefault().Name

    ReplyDelete