Search code examples
c#expression-trees

How to work around: AmbiguousMatchException in Expression.Property(myNewExpression, "nameOfproperty")


I have a class that looks something like this:

public class MyClass {
    public string id { get; set; }
    public string Id { get; set; }
    public string SomethingMore {get; set;}
}

I don't control the class. So I have to live with the fact that both id (lowercase i) and Id (uppercase I) exist. Like it or not, I cannot change this, hence this answer answers my why, but it does not answer my how-to question.

In my Expression tree I have:

var newExpression = Expression.New(typeof(MyClass).GetConstructor(Type.EmptyTypes))

var propertyExpression = Expression.Property(newExpression, "Id");

The second line throws an Ambiguous Match Exception, because Expression.Property(..) is case insensitive - e.g. Expression.Property(newExpression, "SomethingMore") does not throw an exception.

What sort of work-around options do I have?

The next step in the code is:

Expression.Assign(propertyExpression, Expression.Constant("someNewValue", typeof(string));

I don't need to assign value to the id property and I know the meaning of id, which is special. I do however need to be able to assign a value to the Id property.

I guess I could create a derived version of my MyClass, that doesn't include the id property, but I need to do this at run-time. If this is the solution, how can it be done? Or, maybe there's a much better solution?

I don't control the MyClass. I only know that a developer would be inclined to define both idand Id in their class.


Solution

  • There are overloads for Expression.Property that allow a more explicit means of accessing the desired property.

    Get the property info explicitly using reflection and use that.

    var type = typeof(MyClass);
    
    var newExpression = Expression.New(type.GetConstructor(Type.EmptyTypes));
    
    PropertyInfo property = type.GetProperty("Id");
    
    var propertyExpression = Expression.Property(newExpression, property);