If i have a product.
var p = new Product { Price = 30 };
and i have the following linq query.
var q = repo.Products().Where
This helper method will gracefully retrieve any expression value, without "compiling hack" :
public static object GetMemberExpressionValue (MemberExpression expression)
{
// Dependency chain of a MemberExpression is of the form:
// MemberExpression expression
// MemberExpression expression.Expression
// ... MemberExpression expression.[...].Expression
// ConstantExpression expression.[...].Expression.Expression <- base object
var dependencyChain = new List();
var pointingExpression = expression;
while (pointingExpression != null)
{
dependencyChain.Add(pointingExpression);
pointingExpression = pointingExpression.Expression as MemberExpression;
}
if (!(dependencyChain.Last().Expression is ConstantExpression baseExpression))
{
throw new Exception(
$"Last expression {dependencyChain.Last().Expression} of dependency chain of {expression} is not a constant." +
"Thus the expression value cannot be found.");
}
var resolvedValue = baseExpression.Value;
for (var i = dependencyChain.Count; i > 0; i--)
{
var expr = dependencyChain[i - 1];
resolvedValue = new PropOrField(expr.Member).GetValue(resolvedValue);
}
return resolvedValue;
}
PropOrField class :
public class PropOrField
{
public readonly MemberInfo MemberInfo;
public PropOrField (MemberInfo memberInfo)
{
if (!(memberInfo is PropertyInfo) && !(memberInfo is FieldInfo))
{
throw new Exception(
$"{nameof(memberInfo)} must either be {nameof(PropertyInfo)} or {nameof(FieldInfo)}");
}
MemberInfo = memberInfo;
}
public object GetValue (object source)
{
if (MemberInfo is PropertyInfo propertyInfo) return propertyInfo.GetValue(source);
if (MemberInfo is FieldInfo fieldInfo) return fieldInfo.GetValue(source);
return null;
}
public void SetValue (object target, object source)
{
if (MemberInfo is PropertyInfo propertyInfo) propertyInfo.SetValue(target, source);
if (MemberInfo is FieldInfo fieldInfo) fieldInfo.SetValue(target, source);
}
public Type GetMemberType ()
{
if (MemberInfo is PropertyInfo propertyInfo) return propertyInfo.PropertyType;
if (MemberInfo is FieldInfo fieldInfo) return fieldInfo.FieldType;
return null;
}
}