Search code examples
c#.netlambdaexpression-treesexpression

Create New Expression from Existing Expression


I have an Expression<Func<T,DateTime>> I want to take the DateTime part of the expression and pull the Month off of it. So I would be turning it into a Expression<Func<T,int>> I'm not really sure how to do this. I looked at the ExpressionTree Visitor but I can't get it to work like I need. Here is an example of the DateTime Expression

DateTimeExpression http://img442.imageshack.us/img442/6545/datetimeexpression.png

Here is an example of what I want to create MonthExpression http://img203.imageshack.us/img203/8013/datetimemonthexpression.png

It looks like I need to create a new MemberExpression that is made up of the Month property from the DateTime expression but I'm not sure.


Solution

  • Yes, that's exactly what you want - and using Expression.Property is the easiest way to do that:

    Expression func = Expression.Property(existingFunc.Body, "Month");
    Expression<Func<T, int>> lambda = 
        Expression.Lambda<Func<T, int>>(func, existingFunc.Parameters);
    

    I believe that should be okay. It works in this simple test:

    using System;
    using System.Linq.Expressions;
    
    class Person
    {
        public DateTime Birthday { get; set; }
    }
    
    class Test
    {
        static void Main()
        {
            Person jon = new Person 
            { 
                Birthday = new DateTime(1976, 6, 19)
            };
    
            Expression<Func<Person,DateTime>> dateTimeExtract = p => p.Birthday;
            var monthExtract = ExtractMonth(dateTimeExtract);
            var compiled = monthExtract.Compile();
            Console.WriteLine(compiled(jon));
        }
    
        static Expression<Func<T,int>> ExtractMonth<T>
            (Expression<Func<T,DateTime>> existingFunc)
        {
            Expression func = Expression.Property(existingFunc.Body, "Month");
            Expression<Func<T, int>> lambda = 
                Expression.Lambda<Func<T, int>>(func, existingFunc.Parameters);
            return lambda;
        }                                        
    }