Convert anonymous object to expression delegate

I have a third-party library that has the following API:

Update<TReport>(object updateOnly, Expression<Func<TReport,bool>> where) 

What I want to do is call this method, but use anonymous objects, such as:

 Update(new {Name = "test"}, new {Id = id}) 

Is it possible to take a second anonymous object and convert it into something like:

 x => x.Id == id. 

So I want to convert the new {Id = id} to a function that accepts TReport and returns bool?

+4
source share
2 answers

Even if I agree with Daniel A. White that this complicates the situation, I worked a little.

But this is unsafe because you are losing strong typing . (You can put everything you want into an anonymous object: it is not connected with objects of "real" properties ... So there is no refactoring, no verification ...)

It has not been tested, so it’s not sure if this is what you want. You can have (if it works) different objects in the "predicate object":

 new {Name="test"}, new{Id=1, Name="test2"}) 

So you might have something like this:

 public static class MyHelpers { public static Expression<Func<TReport, bool>> CreatePredicate<TReport>(this object predicateObject) { var parameterExpression = Expression.Parameter(typeof(TReport), "item"); Expression memberExpression = parameterExpression; var objectDictionary = MakeDictionary(predicateObject); foreach (var entry in objectDictionary.Where(entry => typeof(TReport).GetProperty(entry.Key) == null)) { throw new ArgumentException(string.Format("Type {0} has no property {1}", typeof(TReport).Name, entry.Key)); } var equalityExpressions = GetBinaryExpressions(objectDictionary, memberExpression).ToList(); var body = equalityExpressions.First(); body = equalityExpressions.Skip(1).Aggregate(body, Expression.And); return Expression.Lambda<Func<TReport, bool>>(body, new[] { parameterExpression }); } private static IDictionary<string, object> MakeDictionary(object withProperties) { var properties = TypeDescriptor.GetProperties(withProperties); return properties.Cast<PropertyDescriptor>().ToDictionary(property => property.Name, property => property.GetValue(withProperties)); } private static IEnumerable<BinaryExpression> GetBinaryExpressions(IDictionary<string, object> dic, Expression expression) { return dic.Select(m => Expression.Equal(Expression.Property(expression, m.Key), Expression.Constant(m.Value))); } } 

eg

 public void Update<TReport>(object updateOnly, object predicateObject) { var predicate = predicateObject.CreatePredicate<TReport>(); yourGenericApi.Update(updateOnly, predicate); } 

EDIT: Since you are losing strong typing security, you should add something like

 foreach (var entry in objectDictionary.Where(entry => typeof(TReport).GetProperty(entry.Key) == null)) { throw new ArgumentException(string.Format("Type {0} has no property {1}", typeof(TReport).Name, entry.Key)); } 

after

 var objectDictionary = MakeDictionary(predicateObject); 
+2
source

If you have a specific value that you want to return functions to, I think you can just do this:

 bool desiredResult = true; Update(new { Name = "test" }, x => desiredResult); 
0
source

All Articles