Linq Expression to Return Property Value

Generic method to get property values with Linq Expression and reflection

The problem is here:

if (response != null)
{
var expr = (MemberExpression)propertyExpression.Body;
var prop = (PropertyInfo)expr.Member;
return (T)prop.GetValue(response);
}

This only works if your expression references a property directly, otherwise propertyExpression.Body will not be a MemberExpression and you'll get a run-time cast error. The three that don't work do not reference a property directly - the first two reverence a method on top of a property (the indexer) and the last references a nested property.

Since all you want is the value of the expression, though, I think you can just do:

if (response != null)
{
Func<TEntity, T> func = propertyExpression.Compile();
return func(response);
}

If you intended to do other things with the expression (like get the name of the property), then you'll need to decide if you want to support expressions that don't reference a property directly and add handlers for that.

LINQ Expression to return Property value?

Easiest way to do this: Use LINQKit (Free, non-restrictive license)

Working version of code:

public static IEnumerable<T> SelectByParameterList<T, PropertyType>(this Table<T> items, IEnumerable<PropertyType> parameterList, Expression<Func<T, PropertyType>> propertySelector, int blockSize) where T : class
{
var groups = parameterList
.Select((Parameter, index) =>
new
{
GroupID = index / blockSize, //# of parameters per request
Parameter
}
)
.GroupBy(x => x.GroupID)
.AsEnumerable();

var selector = LinqKit.Linq.Expr(propertySelector);

var results = groups
.Select(g => new { Group = g, Parameters = g.Select(x => x.Parameter) } )
.SelectMany(g =>
/* AsExpandable() extension method requires LinqKit DLL */
items.AsExpandable().Where(item => g.Parameters.Contains(selector.Invoke(item)))
);

return results;
}

Example usage:

    Guid[] local_refill_ids = Refills.Select(r => r.Id).Take(20).ToArray();

IEnumerable<Refill> results = Refills.SelectByParameterList(local_refill_ids, r => r.Id, 10); //runs 2 SQL queries with 10 parameters each

Thanks again for all your help!

How to create an expression getting a property dynamically using LinqExpression in c#?

Lambda body does not require all of their arguments to be expressions.
Remove the filter from the list of lambda params and turn the type of the filter arg to SearchFilter like this:

static void Main(string[] args)
{
...
var studentParamExpr = Expression.Parameter(typeof(Student), "s");
var lambdaExpr = Expression.Lambda(
CreateStudentAddressRuleAccessor(studentParamExpr, filter),
new ParameterExpression[] { studentParamExpr });
var expression = lambdaExpr.Compile().DynamicInvoke(student);
Console.WriteLine($"Lambda expression = {lambdaExpr}");
Console.WriteLine($"Expression = {expression}");
}

public static Expression CreateStudentAddressRuleAccessor(ParameterExpression student, SearchFilter filter)
{
var resultExpr = Expression.Property(Expression.Property(student, "Address"), filter.Rule);
return resultExpr;
}

c# Lambda Expression - Get property value from string

var parameterExp = Expression.Parameter(typeof(Product), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);

Expression<Func<Product, bool>> predicate = Expression.Lambda<Func<T, bool>>
(containsMethodExp, parameterExp);

var query = query.Where(predicate);

Get property value with Expression without knowing target type at compile time

Yes:

var arg = Expression.Parameter(typeof(object));
var expr = Expression.Property(Expression.Convert(arg, type), propertyName);

Note: the return type (object) means that many types will need to be boxed. Since you mention you are doing this for filtering: if possible, try to avoid this box by creating instead a Func<object,bool> that does any comparisons etc internally without boxing.

How to set a property value from an expression tree?

As soon as the input lambda expression represents member accessor, you can use Expression.Assign passing the input lambda expression body and parameter representing the value, e.g.

static Action<double> GetSetterForX(Expression<Func<double>> expression)
{
var parameter = Expression.Parameter(typeof(double), "value");
var body = Expression.Assign(expression.Body, parameter);
var lambda = Expression.Lambda<Action<double>>(body, parameter);
return lambda.Compile();
}


Related Topics



Leave a reply



Submit