'Construct LambdaExpression for nested property from string
I am trying to create a lambda expression for a nested property at run-time from the name of the propert. Basically I am trying to create the lambda expression specified by:
var expression = CreateExpression<Foo, object>(foo => foo.myBar.name);
private static Expression CreateExpression<TEntity, TReturn>(Expression<Func<TEntity, TReturn>> expression)
{
return (expression as Expression);
}
With the classes:
class Foo
{
public Bar myBar { get; set; }
}
class Bar
{
public string name { get; set; }
}
However all I am given is the type of Foo and the string "myBar.name"
If it were a normal property such as just needing the value "myBar" then I could use the following:
private static LambdaExpression GetPropertyAccessLambda(Type type, string propertyName)
{
ParameterExpression odataItParameter = Expression.Parameter(type, "$it");
MemberExpression propertyAccess = Expression.Property(odataItParameter, propertyName);
return Expression.Lambda(propertyAccess, odataItParameter);
}
However this code does not work for nested properties and I'm not sure how to create the LambdaExpression to do the work of foo.myBar.name.
I think it's going to be something like this:
GetExpression(Expression.Call(GetExpression(Foo, "myBar"), "name"))
But I can't seem to work out how to get it all working, or if there's a better way to do this at run-time.
Solution 1:[1]
Do you mean:
static LambdaExpression CreateExpression(Type type, string propertyName) {
var param = Expression.Parameter(type, "x");
Expression body = param;
foreach (var member in propertyName.Split('.')) {
body = Expression.PropertyOrField(body, member);
}
return Expression.Lambda(body, param);
}
For example:
class Foo {
public Bar myBar { get; set; }
}
class Bar {
public string name { get; set; }
}
static void Main() {
var expression = CreateExpression(typeof(Foo), "myBar.name");
// x => x.myBar.name
}
?
Solution 2:[2]
For this method, propertyPath is "Car", "Colour" for Driver.Car.Colour.
public static MemberExpression NestedProperty(Expression propertyHolder, params string[] propertyPath)
{
MemberExpression memberExpression = Expression.Property(propertyHolder, propertyPath[0]);
foreach (var member in propertyPath.Skip(1))
{
memberExpression = Expression.Property(memberExpression, member);
}
return memberExpression;
}
Solution 3:[3]
To construct a lambda expression but with an inline solution you can do:
var param = Expression.Parameter(typeOf(FooBar), "x");
// you "concat" your expression here :
var propertyExpression = Expression.PropertyOrField(param, "myBar");
propertyExpression = Expression.PropertyOrField(propertyExpression, "name");
// expected result : "x.myBar.name" as a body expression
var expression = Expression.Lambda(propertyExpression, param);
// x => x.myBar.name
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Marc Gravell |
| Solution 2 | Zoidbergseasharp |
| Solution 3 |
