views:

101

answers:

1

If I want to get a user input from Console to my Expression Tree. What is the best way to do it? and how to make variable 'name' duck typing?

Here are my code.

using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.Linq;
using Microsoft.Linq.Expressions;

namespace ExpressionTree
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Expression> statements = new List<Expression>();

            // Output
            MethodInfo Write = typeof(System.Console).GetMethod("Write", new Type[] { typeof(string) });
            ConstantExpression param = Expression.Constant("What is your name? ", typeof(string));
            Expression output = Expression.Call(null, Write, param);
            statements.Add(output);

            // Input
            MethodInfo ReadLine = typeof(System.Console).GetMethod("ReadLine");
            ParameterExpression exprName = Expression.Variable(typeof(String), "name");
            Expression exprReadLine = Expression.Call(null, ReadLine);

            // .NET 4.0 (DlR 0.9) from Microsoft.Scripting.Core.dll
            // Expression.Assign and Expression.Scope
            ScopeExpression input = Expression.Scope(Expression.Assign(exprName, exprReadLine), exprName);
            statements.Add(input);

            // Create the lambda
            LambdaExpression lambda = Expression.Lambda(Expression.Block(statements));

            // Compile and execute the lambda
            lambda.Compile().DynamicInvoke();

            Console.ReadLine();
        }
    }
}
A: 

Expression trees are designed to perform a fixed operation - in particular, the member-access is going to want a known MemberInfo (etc) at the point of expression tree creation (since they are immutable).

You could duplicate the generated code from dynamic if you are playing with 4.0, but to be honest, the better approach in this scenario is simply: don't use an expression tree.

Either reflection or ComponentModel (TypeDescriptor) would be ideal for this dynamic access to a member.

Also - calling Compile on something you use only once isn't saving any time, and using DynamicInvoke isn't either... you need to use the typed delegate form (Invoke).

Marc Gravell