Search code examples
c#linqdynamicentity-framework-6expression-trees

Building expression tree dynamically with typecasting


(Edited):

I have my class:

public class Employee
{
    public int Id {get;set;}
    public string Name {get;set;}
}

public class ContractEmployee : Employee
{
    public int ContractMonth {get;set;}
}

public class Remuneration
{
    public int Id {get;set;}
    public Employee Employee {get;set;}
    public int Amount {get;set;}
}

I can query Contract month like this (Using Employee as base type):

1st case:

r => (r.Employee as ContractEmployee).Amount > 10000 

Corrected:

r => (r.Employee is ContractEmployee) && r.Amount > 10000

2nd case:

_context.Remunerations.Where(r => (r.Employee as ContractEmployee).ContractMonth > 10);

I need to create this expression

r => (r.Employee as ContractEmployee).ContractMonth > 10

dynamically.

Suppose, I get this string "Employee.ContractMonth > 10" and it will be known that I need to convert it onto ContractEmployee while coding.

I can convert this into an expression as follows:

PropertyInfo p = typeof(Remuneration).GetProperty("Employee.ContractMonth");
ParameterExpression lhsParam = Expression.Parameter(typeof(Remuneration));
Expression lhs = Expression.Property(lhsParam, p);
Expression rhs = Expression.Constant(Convert.ChangeType("10", pi.PropertyType));
Expression myoperation = Expression.MakeBinary(ExpressionType.GreaterThan, lhs, rhs);

The above code will not work because "ContractMonth" does not belong to the class "Employee".

How can I typecast Employee as ContractEmployee using Expression Tree: r => (r.Employee as ContractEmployee).ContractMonth > 10

Thanks


Solution

  • You are trying to access property on the wrong object.

    You have

    r => (r.Employee as ContractEmployee).Amount > 10000 
    

    While it should be:

    r => (r.Employee is ContractEmployee) && r.Amount > 10000
    

    I'm leaving it to you to build expression from this lambda

    Something like this:

    Expression.And(
                Expression.TypeIs(Expression.Parameter(typeof(Employee), "r"), typeof(ContractEmployee)),
                Expression.GreaterThan(Expression.Property(Expression.Parameter(typeof(Employee), "r"), "Ammount"), Expression.Constant(10000))
            )