using System.Collections.Generic;
using System.Linq.Expressions;
using Type = System.Type;
public static void Main()
var list = new[] {new Foo
Bar = new Bar{Prop1="AA",Prop2="Bb"} ,
Bars =new List<Bar>(){ new Bar{Prop1="AA",Prop2="Bb"} }
Property1 = "foo2",Property2="a",Bar= new Bar{Prop1="AA",Prop2="Bb"} }};
Bar = x.Bar.SelectDynamic("Prop1")
.SelectDynamic("Property1","Bar");
public string Property1 {get;set;}
public string Property2 {get;set;}
public List<Bar> Bars{get;set;}
public string Prop1{get;set;}
public string Prop2{get;set;}
public static class ExpressionTreeHelper
public static IEnumerable<dynamic> SelectDynamic<T>(this IEnumerable<T> source, params string[] properties)
return SelectProperties<T>(source.AsQueryable(), properties).Cast<dynamic>();
public static dynamic SelectDynamic(this object obj,params string[] propertyNames)
var properties = obj.GetType().GetProperties().Where(p => propertyNames.Contains(p.Name));
var lambdaParameterExpression = Expression.Parameter(obj.GetType());
var propertyExpressions = properties.Select(p => Expression.Property(lambdaParameterExpression, p));
var anonymousType = AnonymousTypeUtils.CreateType(properties.ToDictionary(p => p.Name, p => p.PropertyType));
var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
var anonymousTypeMembers = anonymousType.GetProperties().Cast<MemberInfo>().ToArray();
var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);
var selectLambdaMethod = GetExpressionLambdaMethod(lambdaParameterExpression.Type, anonymousType);
var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { lambdaParameterExpression } };
var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);
return selectBodyLambdaExpression.Compile().DynamicInvoke(obj);
private static IQueryable SelectProperties<T>(this IQueryable<T> queryable, IEnumerable<string> propertyNames)
var properties = typeof(T).GetProperties().Where(p => propertyNames.Contains(p.Name));
var lambdaParameterExpression = Expression.Parameter(typeof(T));
var propertyExpressions = properties.Select(p => Expression.Property(lambdaParameterExpression, p));
var anonymousType = AnonymousTypeUtils.CreateType(properties.ToDictionary(p => p.Name, p => p.PropertyType));
var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
var anonymousTypeMembers = anonymousType.GetProperties().Cast<MemberInfo>().ToArray();
var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);
var selectLambdaMethod = GetExpressionLambdaMethod(lambdaParameterExpression.Type, anonymousType);
var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { lambdaParameterExpression } };
var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);
var selectMethod = GetQueryableSelectMethod(typeof(T), anonymousType);
var selectedQueryable = selectMethod.Invoke(null, new object[] { queryable, selectBodyLambdaExpression }) as IQueryable;
return selectedQueryable;
private static MethodInfo GetExpressionLambdaMethod(Type entityType, Type funcReturnType)
var prototypeLambdaMethod = GetStaticMethod(() => Expression.Lambda<Func<object, object>>(default(Expression), default(IEnumerable<ParameterExpression>)));
var lambdaGenericMethodDefinition = prototypeLambdaMethod.GetGenericMethodDefinition();
var funcType = typeof(Func<,>).MakeGenericType(entityType, funcReturnType);
var lambdaMethod = lambdaGenericMethodDefinition.MakeGenericMethod(funcType);
private static MethodInfo GetQueryableSelectMethod(Type entityType, Type returnType)
var prototypeSelectMethod = GetStaticMethod(() => Queryable.Select(default(IQueryable<object>), default(Expression<Func<object, object>>)));
var selectGenericMethodDefinition = prototypeSelectMethod.GetGenericMethodDefinition();
return selectGenericMethodDefinition.MakeGenericMethod(entityType, returnType);
private static MethodInfo GetStaticMethod(Expression<Action> expression)
var lambda = expression as LambdaExpression;
var methodCallExpression = lambda.Body as MethodCallExpression;
return methodCallExpression.Method;