none
Need help using Expression Tree classes to create delegates for RelayCommand instances RRS feed

  • Question

  • I am trying to write a C# WPF MVVM app and am putting code in a ViewModelBase class to use Reflection to find methods and properties in the derived ViewModel class that are annotated with a custom CommandAttribute.  This information would then be used to create a list of RelayCommands that can be referenced from the view's XAML.  This is to avoid clogging the ViewModel class with repetitive RelayCommand properties.

    I am using Visual Studio 2008, so please only suggest solutions that can be accomplished with the 3.5 framework.  This is my first experience using the LINQ Expression classes so I have been groping for the solution and Bing'ing for an example for 3 days.

    The compile-time solution would be instantiate the RelayCommand object with the first constructor argument being an Action<object> delegate using lambda expression would look like one of the following two examples:

    p => SomeExecuteMethod()

    p => AnotherExecuteMethod(p)

    depending on whether or not the execute method takes a parameter.

    Here is my solution, so far:

            private Action<object> CreateExecuteDelegate( MethodInfo mi )
            {
                var instance = Expression.Parameter( GetType(), "instance" );
                var p = Expression.Parameter( typeof( object ), "p" );
                MethodCallExpression methodCall;

                if ( mi.GetParameters().Length == 1 )
                {
                    methodCall = Expression.Call( instance, mi, p );
                }
                else
                {
                    methodCall = Expression.Call( instance, mi );
                }

                var execLambda = Expression.Lambda<Action<object>>( methodCall, p );
                Action<object> executeDelegate = execLambda.Compile();

                return executeDelegate;
            }

    It is failing with an InvalidOperationException with the text of "Lambda Parameter not in scope" on the execLambda.Compile() call.  The error is the same whether the method takes an argument or not.

    Any help would be appreciated.

    • Moved by Mike FengModerator Tuesday, October 30, 2012 6:08 AM Data (From:.NET Base Class Library)
    • Moved by Alexander Sun Wednesday, October 31, 2012 9:03 AM Move to more appropriate forum. (From:ADO.NET Entity Framework and LINQ to Entities)
    Sunday, October 28, 2012 12:39 PM

Answers

  • Hi Rick,


    You’ve declared two ParameterExpressions, namely “instance” and “p”. Only the latter is in scope in the LambdaExpression, hence the error.


    What’s the instance on which you want to invoke “SomeExecuteMethod” (or generally, “mi”, in your code)? You’ll want to capture that object in a ConstantExpression, assigned to “instance”, rather than using a ParameterExpression there.


    Thanks,

    Gaurav

    Friday, December 7, 2012 8:22 PM

All replies

  • Hi Rick,

    I have moved this thread to a more appropriate forum for better support.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, October 30, 2012 6:12 AM
    Moderator
  • What is the correct forum for questions about how to use the Expression tree classes?

    My question has been bounced around with no reply and I am not sure that it is in the correct forum even now since it has nothing to do with ADO.NET or LINQ to Entities.

    Nonetheless I am still looking for an answer.

    Thanks!

    Sunday, November 4, 2012 11:34 AM
  • Hi Rick,

    I am sorry I misunderstand the issue scope.

    Now I am trying to involve some other one into this case. Wait it patiently, thank you.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, November 8, 2012 3:48 PM
    Moderator
  • It is very disappointing that nobody has any assistance to provide!

    I still have use for this technique if a solution is suggested.

    Rick Burke

    Friday, November 23, 2012 4:02 PM
  • Hi Rick,


    You’ve declared two ParameterExpressions, namely “instance” and “p”. Only the latter is in scope in the LambdaExpression, hence the error.


    What’s the instance on which you want to invoke “SomeExecuteMethod” (or generally, “mi”, in your code)? You’ll want to capture that object in a ConstantExpression, assigned to “instance”, rather than using a ParameterExpression there.


    Thanks,

    Gaurav

    Friday, December 7, 2012 8:22 PM
  • Gaurav,

    Thanks for your response.  It was just what I needed!

    Rick

    Sunday, December 9, 2012 10:58 PM