I am using reflection to create a lambda function. It works with most items I try it with, however on one of the properties it keeps throwing an Ambiguous Match Exception.
The code looks like this. The error happens when it hits Expression.PropertyOrField
. The property I am using is of type decimal?
. I think it might have to do with the fact that it is a nullable type, but I'm not sure.
public static LambdaExpression CreateExpression(Type type, string propertyName, ref Type returnType)
{
var param = Expression.Parameter(type, "x");
Expression body = param;
foreach (var member in propertyName.Split('.'))
{
body = Expression.PropertyOrField(body, member);
}
returnType = body.Type;
return Expression.Lambda(body, param);
}
I see only one way such exception might be thrown in this case: you have multiple properties with the same name but different casing, like this:
public class Test {
public decimal? testProp { get; set; }
public decimal? TestProp { get; set; }
}
Or fields:
public class Test {
public decimal? testProp;
public decimal? TestProp;
}
Note that property with the same name might be in any parent class up hierarchy also:
public class BaseTest {
public decimal? testProp { get; set; }
}
public class Test : BaseTest {
public decimal? TestProp { get; set; } // also fails
}
The reason is Expression.PropertyOrField
does this to search for desired property:
type.GetProperty(propertyOrFieldName, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
Note BindingFlags.IgnoreCase
and BindingFlags.FlattenHierarchy
. So you cannot tell Expression.PropertyOrField
to search in case-sensitive manner.
However I would argue that to have multiple properties with the same name is a bad practice anyway and should be avoided.