This project has moved and is read-only. For the latest updates, please go here.

Evaluating void expressions

Feb 28, 2014 at 10:30 AM
Hi. I recently translated a Java project to C# that uses an express evaluator. While extensively searching for an equivalent evaluator in C# (translating the original evaluator written in Java would've been a pain in the ass) I found your evaluator. Congratulations for this project, it is much simpler to integrate and use than other options, I managed to integrate it succesfully in just a couple of hours with only one small change (I needed the TypeRegistry to be global to all expressions, like a context).
I only have one problem. Your evaluator seems to fail when evaluating an expression that has no return type. It throws the following error: "No coercion operator is defined between types 'System.Void' and 'System.Object'."
For example, if I register an object, e.g Person and I call a void method on that object that let's say it sets something on that instance, it fails to evaluate the expression.
I tried to fiddle with the code but with no success.
Can you please tell me what can be done about this or if you are planning to fix this?

Thanks.
Feb 28, 2014 at 2:58 PM
Mar 1, 2014 at 2:48 PM
Kerasphorus,

Do you need to compile an expression "instance.Foo()" where Foo is a method that returns void? I would assume that you know beforehand that the method is going to be called instead of returning a value.

I have been able to get it to work (more or less), you need to compile to an Action<T> instead of a Func<T>. I created a new method on the CompiledExpression classes named CompileCall().
        public Action CompileCall()
        {
            if (Expression == null) Expression = BuildTree();
            return Expression.Lambda<Action>(Expression).Compile();
        }
For dynamic scope, it's a bit more difficult. You need to know beforehand whether your MemberAccess is going to return a value or not. In this case I think I would have to check if the memberAccess is the LAST token to be compiled, along with a flag that the expression is going to be called instead of returning a value.

In the dynamic side the following should be called IF the member is returning void:
                    var binderM = Binder.InvokeMember(
                            CSharpBinderFlags.ResultDiscarded,
                            membername,
                            null,
                            type,
                            expArgs.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null))
                        );

                    return Expression.Dynamic(binderM, typeof(void), expArgs);
I'll probably commit to a branch once I get the dynamic part working.
Mar 3, 2014 at 12:36 PM
Just to let you know I've committed changes to the main branch with support for compiling to an Action. Also have a Call method in there that does what Eval does, but doesn't return anything.