using System.Linq.Expressions;
using System.Collections.Generic;
public static void Main()
var thing = new Thing() { ID = 1, Name = "Tom" };
var ex = thing.AsExpando<Thing>(x => x.Name);
string output = JsonConvert.SerializeObject(ex);
Console.WriteLine(output);
var things = new List<Thing>()
new Thing() { ID = 2, Name = "Steve", Age = 8 },
new Thing() { ID = 2, Name = "Steve" },
new Thing() { ID = 2, Name = "Steve", Age = 9 },
var exes = things.AsExpando<Thing>(x => x.Name);
output = JsonConvert.SerializeObject(exes);
exes = things.AsExpando<Thing>(x => x.Name);
output = JsonConvert.SerializeObject(exes);
Console.WriteLine(Extensions.CompileCount);
public string Name { get; set; }
public Func<T, object> Func { get; set; }
public int ID { get; set; }
public string Name { get; set; }
public int Age { get ;set; }
public static class Extensions
static Dictionary<Type, Object> typedic = new Dictionary<Type, Object>();
public static int CompileCount = 0;
public static IEnumerable<ExpandoObject> AsExpando<T>(this IEnumerable<T> items, params Expression<Func<T, object>>[] props)
return items.Select(x => AsExpando(x, props));
public static ExpandoObject AsExpando<T>(this T item, params Expression<Func<T, object>>[] props )
var expando = new ExpandoObject();
var dict = expando as IDictionary<string, object>;
Dictionary<string, Compiled<T>> propdic = null;
if (!typedic.ContainsKey(typeof(T)))
propdic = new Dictionary<string, Compiled<T>>();
typedic.Add(typeof(T), propdic);
propdic = (Dictionary<string, Compiled<T>>)typedic[typeof(T)];
foreach (var prop in props)
Func<T, object> func = null;
var bodyString = prop.Body.ToString();
if (!propdic.ContainsKey(bodyString))
name = GetFullPropertyName<T, object>(prop);
var comp = new Compiled<T>() { Name = name, Func = func };
propdic.Add(bodyString, comp);
var comp = propdic[bodyString];
if (String.IsNullOrEmpty(name))
static string GetFullPropertyName<T, TProperty> (Expression<Func<T, TProperty>> exp)
MemberExpression memberExp;
if (!TryFindMemberExpression(exp.Body, out memberExp))
var memberNames = new Stack<string>();
memberNames.Push(memberExp.Member.Name);
while (TryFindMemberExpression(memberExp.Expression, out memberExp));
return string.Join(".", memberNames.ToArray());
private static bool TryFindMemberExpression
(Expression exp, out MemberExpression memberExp)
memberExp = exp as MemberExpression;
if (IsConversion(exp) && exp is UnaryExpression)
memberExp = ((UnaryExpression)exp).Operand as MemberExpression;
private static bool IsConversion(Expression exp)
exp.NodeType == ExpressionType.Convert ||
exp.NodeType == ExpressionType.ConvertChecked