Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Action delegate. How to get the instance that call the method

I have an Action and I wonder how could I access the instance that call the method.

Exemple:

this.FindInstance(() => this.InstanceOfAClass.Method());
this.FindInstance(() => this.InstanceOfAClass2.Method());
this.FindInstance(() => this.InstanceOfAClass3.Method());



    public void FindInstance(Action action)
    {
        // The action is this.InstanceOfAClass.Method(); and I want to get the "Instance"
        // from "action"
    }

Thank you

like image 605
Jean-Philippe Leclerc Avatar asked Mar 23 '11 18:03

Jean-Philippe Leclerc


People also ask

What is the use of Action delegate in C#?

The Action delegate is generally used for those methods which do not contain any return value, or in other words, Action delegate is used with those methods whose return type is void. It can also contain parameters of the same type or of different types.

How do you call a delegate method in C#?

A delegate can be declared using the delegate keyword followed by a function signature, as shown below. The following declares a delegate named MyDelegate . public delegate void MyDelegate(string msg); Above, we have declared a delegate MyDelegate with a void return type and a string parameter.

What is instance delegate?

A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.

How do you instantiate a delegate?

Use the new keyword to instantiate a delegate. When creating a delegate, the argument passed to the new expression is written similar to a method call, but without the arguments to the method.


2 Answers

I think you're looking for the Delegate.Target property.

EDIT: Okay, now I see what you're after, and you need an expression tree representing the action. Then you can find the target of the method call as another expression tree, build a LambdaExpression from that, compile and execute it, and see the result:

using System;
using System.Linq.Expressions;

class Test
{
    static string someValue;

    static void Main()
    {
        someValue = "target value";

        DisplayCallTarget(() => someValue.Replace("x", "y"));
    }

    static void DisplayCallTarget(Expression<Action> action)
    {
        // TODO: *Lots* of validation
        MethodCallExpression call = (MethodCallExpression) action.Body;

        LambdaExpression targetOnly = Expression.Lambda(call.Object, null);
        Delegate compiled = targetOnly.Compile();
        object result = compiled.DynamicInvoke(null);
        Console.WriteLine(result);
    }
}

Note that this is incredibly brittle - but it should work in simple cases.

like image 173
Jon Skeet Avatar answered Nov 15 '22 17:11

Jon Skeet


Actually I don't know if you can do it in this way. Delegate class contains only two properties: Target and Method. Accessing Target won't work because you are creating a new anonymous method, so the property will return the class in which FindInstance method is called.

Try something like this instead:

FindInstance(this.MyInstance.DoSomething);

And then access the Target property as follows:

public void FindInstance(Action action)
{
    dynamic instance = action.Target;
    Console.WriteLine(instance.Property1);
}
like image 26
as-cii Avatar answered Nov 15 '22 18:11

as-cii