-
-
Save charlessolar/20f453de023ff75edeb8 to your computer and use it in GitHub Desktop.
public static IQueryable<dynamic> ToDynamic<T>(this IQueryable<T> query, ISet<String> fields) | |
{ | |
var pocoType = typeof(T); | |
var itemParam = Expression.Parameter(pocoType, "x"); | |
var members = fields.Select(f => Expression.PropertyOrField(itemParam, f)); | |
var addMethod = typeof(IDictionary<string, object>).GetMethod( | |
"Add", new Type[] { typeof(string), typeof(object) }); | |
var elementInits = members.Select(m => Expression.ElementInit(addMethod, Expression.Constant(m.Member.Name), Expression.Convert(m, typeof(Object)))); | |
var expando = Expression.New(typeof(ExpandoObject)); | |
var lambda = Expression.Lambda<Expression<Func<T, dynamic>>>(Expression.ListInit(expando, elementInits), itemParam); | |
return query.Select(lambda.Compile()); | |
} | |
public static IQueryable<T> FromDynamic<T>(this IQueryable<dynamic> query) where T : class, new() | |
{ | |
var itemParam = Expression.Parameter(typeof(ExpandoObject), "x"); | |
var members = typeof(T).GetProperties().Where(p => p.CanWrite).Select(f => Expression.Property(itemParam, f)); | |
var selector = Expression.MemberInit(Expression.New(typeof(T)), | |
members.Select(m => Expression.Bind(typeof(T).GetMember(m.Member.Name).Single(), m)) | |
); | |
var lambda = Expression.Lambda<Expression<Func<dynamic, T>>>(selector, itemParam); | |
return query.Select(lambda.Compile()); | |
} | |
public static T FromDynamic<T>(this IDictionary<string, object> dictionary) where T : class, new() | |
{ | |
var bindings = new List<MemberBinding>(); | |
foreach (var sourceProperty in typeof(T).GetProperties().Where(x => x.CanWrite)) | |
{ | |
var key = dictionary.Keys.SingleOrDefault(x => x.Equals(sourceProperty.Name, StringComparison.OrdinalIgnoreCase)); | |
if (string.IsNullOrEmpty(key)) continue; | |
var propertyValue = dictionary[key]; | |
bindings.Add(Expression.Bind(sourceProperty, Expression.Constant(propertyValue))); | |
} | |
Expression memberInit = Expression.MemberInit(Expression.New(typeof(T)), bindings); | |
return Expression.Lambda<Func<T>>(memberInit).Compile().Invoke(); | |
} | |
public static dynamic ToDynamic<T>(this T obj, ISet<String> fields) | |
{ | |
IDictionary<string, object> expando = new ExpandoObject(); | |
var pocoType = typeof(T); | |
foreach (var f in fields) | |
{ | |
var propertyExpression = Expression.Property(Expression.Constant(obj), pocoType.GetProperty(f)); | |
var currentValue = Expression.Lambda<Func<string>>(propertyExpression).Compile().Invoke(); | |
expando.Add(f, currentValue); | |
} | |
return expando as ExpandoObject; | |
} |
@cmalcom Sorry gists don't seem to send notifications when comments come in...
This code is from 2014 or 2015 - when C# 5.0 just came out - as an example of some cool dynamic expression compiling.
This is still the best way to create dynamic objects based on a filtered list of fields, but I'm afraid I can't help much with errors I no longer work on the project where this was needed. Are you targeting 4.5? They could have changed something after I wrote this to break something. From the error you are seeing it seems there's a missing Expression.Cast - take a look at dynamic lambda compiling in C#. There's not a lot written about it but it can help
@cmalcom line 15 should be chamged to var lambda = Expression.Lambda<Func<T, dynamic>>(Expression.ListInit(expando, elementInits), itemParam)
lambda is now of type Expression<Func<T, dynamic>>
and final on line 17 return query.Select(lambda.Compile());
you can leave out the call to Compile() return query.Select(lambda);
I was unable to get it work with .Net 4.5. Another way: https://gist.github.com/gh0stwizard/e2394cf09cd1eac01c1e5a3c22e0d014
I know its been a couple years but this is something I've been looking at doing. Problem is that I get an error...
in line 15, that I have not been able to track down.
Any suggestion?