I am wanting to create a MemberExpression knowing only the field name; eg:
public static Expression<Func<TModel, T>> GenerateMemberExpression<TModel, T>(string fieldName)
{
PropertyInfo fieldPropertyInfo;
fieldPropertyInfo = typeof(TModel).GetProperty(fieldName);
var entityParam = Expression.Parameter(typeof(TModel), "e"); // {e}
var columnExpr = Expression.MakeMemberAccess(entityParam, fieldPropertyInfo); // {e.fieldName}
var lambda = Expression.Lambda(columnExpr, entityParam) as Expression<Func<TModel, T>>; // {e => e.column}
return lambda;
}
The problem with the above is that the field type must be strongly typed. Passing "object" in as the field type doesn't work. Is there any way to generate this? Even Dynamic LINQ doesn't appear to work.
There are a number of issues with your code:
fieldName
, but you are getting a property out with it.Expression.Lambda
method to generate the expression, which may choose an inappropriate delegate-type if the type-argument T
passed to the method is not the same as the property-type. In this case, the as
cast from the expression to the method's return-type will fail and evaluate to null
. Solution: Use the generic Lambda
method with the appropriate type-arguments. No casting required.T
, but not when more complicated conversions such as boxing / lifting are required. Solution: Use the Expression.Convert
method where necessary.Here's an update to your sample that addresses these issues:
public static Expression<Func<TModel, T>> GenerateMemberExpression<TModel, T>
(string propertyName)
{
var propertyInfo = typeof(TModel).GetProperty(propertyName);
var entityParam = Expression.Parameter(typeof(TModel), "e");
Expression columnExpr = Expression.Property(entityParam, propertyInfo);
if (propertyInfo.PropertyType != typeof(T))
columnExpr = Expression.Convert(columnExpr, typeof(T));
return Expression.Lambda<Func<TModel, T>>(columnExpr, entityParam);
}
This will make all of the following calls succeed:
GenerateMemberExpression<FileInfo, string>("Name");
GenerateMemberExpression<string, int>("Length");
// Reference conversion
GenerateMemberExpression<FileInfo, object>("Name");
//Boxing conversion
GenerateMemberExpression<string, object>("Length");
//Lifted conversion
GenerateMemberExpression<string, int?>("Length");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With