Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a reference to the object that called a method?

Tags:

c#

.net-4.0

I have a dll that includes:

public abstract class Module
{
   internal int ID;

   public abstract void ModuleStart();

}

public void function1() {}
public void function2() {}
//etc...

And then I have another dll that references the above dll and has:

class MyModule : Module
{
   public override void ModuleStart()
   {
      function1();

   }

}

What I'd like to be able to do is have function1 known the value of the calling module's ID, without it being passed in. Is there a way to do this? Basically what I'm trying to do is, the main Module DLL is loaded up, a method is run that loads in the second dll, uses reflection to make sure it has a child of Module, assigns it an ID and runs ModuleStart. MyModule can then do what it needs, calling functions from the first dll in order to access internal protected memory, but when the functions are called they need to know the ID of the Module that called them. Is this possible? MyModule has no knowledge of its ID, nor an ability to change it.

like image 373
cost Avatar asked Feb 13 '13 23:02

cost


2 Answers

.NET 4.5 adds some functionality to do something similar to this with the CallerMemberNameAttribute. Here's a sample from the docs:

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}
like image 89
p.s.w.g Avatar answered Nov 02 '22 15:11

p.s.w.g


A few people have suggested using the call stack to get the module information. If you want to get the type of object that made the call, it's not too bad. Unfortunately there is no feasible (ie: simple, portable and functional) method to extract instance information from data in the call stack. There are several reasons why, including problems with optimization inlining methods that then do not show on the stack... which can interfere with calling type detection as well.

Given this fact, the short answer is that you have to provide a Module object as a parameter to the methods you are calling in the DLL. The method suggested by @p.s.w.g is one way of achieving this, but has the disadvantage of potentially polluting the symbol space of the Module class. This can be solved by having the Module class implement a protected or public API member that exposes the functions you want to provide:

public abstract class Module
{
    internal int ID;

    public class APIWrapper
    {
        Module module;

        public APIWrapper(Module module)
        {
            this.module = module;
        }

        public void method1() { apiimpl.method1(this.module); }
        public int method2() { return apiimpl.method2(this.module); }
    }

    public readonly APIWrapper API;

    public Module()
    {
        ID = generate_module_identity();
        API = new APIWrapper(this);
    }

    public abstract void ModuleStart();
}

internal static class apiimpl
{
    public static void method1(Module module) { ... }
    public static int method2(Module module) { ... }
}

The other developers can then use it this way:

class MyModule : Module
{
    public override void ModuleStart()
    {
        API.method1();
    }
}

This encapsulates the methods that your DLL exposes, without introducing too much pollution of the symbol space of the Module class hierarchy.

[opinion type="my" value="YMMV"]

However, I suggest that you seriously reconsider using this type of abstraction. If the methods you are calling require some information about the specific Module instance that is calling them, it should be clear in the method's parameters. Encouraging your team to follow guidelines that lead to clarity can be more important than finding ways to abstract away small details.

[/opinion]

like image 33
Corey Avatar answered Nov 02 '22 15:11

Corey