locked
Determining parameter values from anonymous delegate/func... RRS feed

  • Question

  • Hi,

    Given the following code,

            public T Execute<T>(Func<T> methodParam)
            {
                return methodParam ();
            }
     
            public void CallMethodsAnonymously<T>()
            {
                T result =  Execute(() => _service.SomeMethod1());
                T result1 = Execute(() => _service.SomeMethod2(someParm1));
                T result2 = Execute(() => _service.SomeMethod3( someParm1, someParm2));
            }
    

    From the Execute method, I am wondering if it’s possible to inspect “methodParam” and extract or determine the number of parameters within the anonymous function body? For example is it possible to determine the values of someParam1 and someParam2 from within the Execute method?
    • Edited by mbsingh Tuesday, October 11, 2011 3:08 AM
    Tuesday, October 11, 2011 3:04 AM

Answers

  • The only way to take different types of delegates as parameter is to define the parameter as the base class of all delegates.

    public static T Execute<T>(Delegate method, params object[] methodParameters)
    {
            return (T)method.DynamicInvoke(methodParameters);
    }
    
    or
    
    public static T Execute<F, T>(F method, params object[] methodParameters) where F : Delegate
    {
            return (T)method.DynamicInvoke(methodParameters);
    }
    

    You would call them like this:

    int result = Execute<int>((Func<string, int>)SomeMethod, "somevalue");
    
    or
    
    int result = Execute<Func<string, int>, int>(SomeMethod, "somevalue");
    

     

    Tuesday, October 11, 2011 10:14 AM

All replies

  • You can do it using the Expression API:

    public static T Execute<T>(Expression<Func<T>> methodParam)
    {
       
    var methodCallExpression = methodParam.Body as MethodCallExpression;
       
    var method = methodCallExpression.Method;
       
    var parameters = method.GetParameters();

       
    return methodParam.Compile()();
    }

    The parameters variable will be an array of ParameterInfo objects which will contain the information you need. Finally, the Compile method actually converts the Expression to an executable delegate. The C# compiler also allows you to call this method with the regular conventions of calling methods that take delegates, with the standard lambdas/anonymous methods.

    Tuesday, October 11, 2011 5:57 AM
  • Thanks...i think you answered this already for me on stackoverflow (assuming you are 'bfree').

    I was wondering if this can be used to also add parameters dynamically to a method:

    Rather than having to define a different delegate for each method signature:

    Func<T1, TResult>
    Func<T1, T2, TResult>
    Func<T1, T2...,Tn, TResult>
    
    

    It would be good to define a single signature Func<TResult>, and add parameters to the method dynamically.  not quite sure how to do that however.

     

    Tuesday, October 11, 2011 6:12 AM
  • The only way to take different types of delegates as parameter is to define the parameter as the base class of all delegates.

    public static T Execute<T>(Delegate method, params object[] methodParameters)
    {
            return (T)method.DynamicInvoke(methodParameters);
    }
    
    or
    
    public static T Execute<F, T>(F method, params object[] methodParameters) where F : Delegate
    {
            return (T)method.DynamicInvoke(methodParameters);
    }
    

    You would call them like this:

    int result = Execute<int>((Func<string, int>)SomeMethod, "somevalue");
    
    or
    
    int result = Execute<Func<string, int>, int>(SomeMethod, "somevalue");
    

     

    Tuesday, October 11, 2011 10:14 AM
  • This looks like one of those places where you might ask yourself if you should really be using delegates here rather than passing objects that implement an interface, as that will give you the flexibility of having a few sets of possible valid methods (if you have a reasonably small set of possible parameter options).

    Knowing a bit more about the context of your problem would allow us to be more helpful as to some better possible solutions, rather than just ways of solving this technical problem that may or may not solve your real problem.

    Tuesday, October 11, 2011 4:53 PM