1

Basically I am compiling expression at run-time and then I am invoking them with the DynamicInvoke methods there are all supposed to return Boolean value, but the problem is that when there is string comparison, it fails. Suppose an expression like that {x.SomeProp == "value"} value of SomeProp is "value" but when I Execute the DynamicInvoke on that expression pass the appropriate object to it and cast the return value to bool I get false as an answer.

This is the code I use to build expression

public static Expression BuildExpression(string propName, Operator op, object value, ParameterExpression paramExp)
{
    var expressionType = new ExpressionType();
    var leftOperand = CreateExpression(paramExp, propName);

    var rightOperand = leftOperand.Type.BaseType == typeof(Enum) ? 
        Expression.Constant(Enum.Parse(leftOperand.Type, value.ToString(), true)) : Expression.Constant(Convert.ChangeType(value, leftOperand.Type));

    var fieldInfo = expressionType.GetType().GetFields(Enum.GetName(typeof(Operator), op));
    var expressionTypeValue = (ExpressionType)fieldInfo.GetValue(op);

    var binaryExpression = Expression.MakeBinary(expressionType, leftOperand, rightOperand);

    returnExpression;
}

private static Expression CreateExpression(ParameterExpression type, string propName)
{
    Expression body = type;
    body = Expression.PropertyOrField(body, propName);

    return body;
}

paramExp basically is this

var param = Expression.Parameter(someObjectType, "x");

now this code is does great job building expressions, then I do

Expression.Lambda(exp, param).Compile();

on it, and then

copiledExp.DynamicInvoke(someObj);

it works okay when comparing int, double, float, decimal and even enum values but recently I have come up to a problem comparing strings. It return false on any expression

this is the view of the expression that is getting built. I mean, this is return by the ToString() method

"(x.SomeStringProp == \"stringValue\")"
Dimitri
  • 2,798
  • 7
  • 39
  • 59
  • Did you try it by explicit casting? Eg: x.SomeProp == new String("value") – Siva Gopal Jun 30 '14 at 16:16
  • can you provide sample output of `Expression.Lambda(exp, param).ToString()`? – Grundy Jun 30 '14 at 16:18
  • Maybe these links can help : http://stackoverflow.com/questions/283537/most-efficient-way-to-test-equality-of-lambda-expressions and (ExpressionComparison.cs) https://source.db4o.com/db4o/trunk/db4o.net/Db4objects.Db4o.Linq/Db4objects.Db4o.Linq/Expressions/ – L.B Jun 30 '14 at 17:50

1 Answers1

0

The equality comparison you have there is between the types string and object because Expression.Constant returns you an expression of type object because ChangeType did as well. This means that you get a reference comparison as if you had written someString == (object)"...".

You'll have to build an expression calling string.Equals or any other equivalent method. Or, you make the constant have type string so that the overloaded equality operator of string is selected.


DynamicInvoke is slower than a direct call because it uses reflection on every call. If you are going for performance with this, compile to a Func<object> and have a cast inside the compiled method to convert the object parameter to the right type.

usr
  • 168,620
  • 35
  • 240
  • 369
  • String implements its own equality operator == which calls String.Equals. Its not a reference compare. – user957902 Jun 30 '14 at 16:30
  • @user957902 expression tree equals does not use overloaded operators. This is not C#. – usr Jun 30 '14 at 16:31
  • The documentation for Expression.Equal says that it will use the overloaded equality operator under the correct circumstances. If you pass two string constant expressions into Expression.Equal you will get an implementing method of {Boolean op_Equality(System.String, System.String)} – user957902 Jun 30 '14 at 17:13
  • 1
    I did not know that. Then, his problem is that `Expression.Constant` returns him an expression of type object. Editing. – usr Jun 30 '14 at 17:15