Get a reference to an object called a method?

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 would like to do is to have function1, known as the identifier value of the calling module, without passing it. Is there any way to do this? Basically, what I'm trying to do is, the main loading DLL module is loaded, the method is launched, which is loaded into the second dll, uses reflection to make sure that it has a child module, assigns an identifier to it and starts ModuleStart. MyModule can do what it needs to, call the functions from the first dll to access the internal protected memory, but when the functions are called, they need to know the identifier of the module they are calling. Is it possible? MyModule does not know its identifier and cannot change it.

+4
source share
3 answers

.NET 4.5 adds some features to do something similar to this with CallerMemberNameAttribute . Here is 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); } 
+12
source

Several people suggested using the call stack to get information about the module. If you want to get the type of object that made the call, this is not so bad. Unfortunately, it is not possible to implement (i.e., a Simple, portable, and functional) method for retrieving instance data from data in the call stack. There are several reasons, including optimization problems, which use methods that then do not appear on the stack ... that may also interfere with the recognition of the type of call.

Given this fact, the short answer is that you should provide a Module object as a parameter for the methods that you call in the DLL. The method suggested by @pswg is one way to achieve this, but it has the disadvantage of potentially polluting the Symbol class symbol space. This can be resolved if the Module class implements a protected or public API member that provides 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) { ... } } 

Other developers may use it as follows:

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

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

[Type of opinion = "mine" value = "YMMV"]

However, I suggest that you seriously review the use of this type of abstraction. If the methods you call require some information about the specific instance of the Module that calls them, it should be clear in the method parameters. Encouraging your team to follow recommendations that lead to clarity may be more important than finding ways to abstract out small details.

[/opinion]

+1
source

If you really only need to get the ID at run time, without passing any arguments to function1 , you can use the inherited methods:

 public abstract class Module { internal int ID; public abstract void ModuleStart(); protected void function1() { System.Console.WriteLine ("function1 called from module {0}", this.ID); } } 

Then from your other modules, calling function1 looks as simple as this:

 class MyModule : Module { public override void ModuleStart() { this.function1(); // the 'this.' is not required } } 

However, I get the point from your comments that you want to make these functions separate from your Module class, as you regularly add new functions. You can do almost the same thing using extension methods to maintain the appearance of non-passing parameters:

 public abstract class Module { internal int ID; public abstract void ModuleStart(); } public static class ModuleExtensions { public static void function1(this Module module) { innerFunction1(module.ID); } internal static void innerFunction1(int ID) { System.Console.WriteLine ("function1 called from module {0}", ID); } } 

Then from your other modules, calling function1 looks as simple as this:

 class MyModule : Module { public override void ModuleStart() { this.function1(); // the 'this.' is required } } 
0
source

All Articles