views:

1378

answers:

6

Is there any way via System.Reflection, System.Diagnostics or other to get a reference to the actual instance that is calling a static method without passing it in to the method itself.

For example, something along these lines

class A  
{  
  public void DoSomething()
  {
    StaticClass.ExecuteMethod();  
  }  
}

class B
{  
  public void DoSomething()
  {
    SomeOtherClass.ExecuteMethod();
  }  
}
public class SomeOtherClass
{
   public static void ExecuteMethod()
   {
      // returns an instance of A if called from class A 
      // or an instance of B if called from class B
      object caller = getCallingInstance();
   }
}

I can get the type using System.Diagnostics.StackTrace.GetFrames, but is there any way to get a reference to the actual instance??

EDIT:
I am aware of the issues with reflection and performance, as well as static to static calls, and that this is generally, perhaps even almost univerally, not the right way to approach this. Part of the reason question is I was curious if it was doable, we are currently passing the instance in.

ExecuteMethod(instance)

and just wondered if this was possible and still being able to access the instance.

ExecuteMethod()

@Steve Cooper: I hadn't considered extension methods. Some variation of that might work. I'll play around with that a bit.

A: 

Why not just have ExecuteMethod take an object. Then you have the instance no matter what?

Jason Punyon
+1  A: 

I do not believe you can. Even the StackTrace and StackFrame classes just give you naming information, not access to instances.

I'm not sure exactly why you'd want to do this, but know that even if you could do it it would likely be very slow.

A better solution would be to push the instance to a thread local context before calling ExecuteMethod that you can retrieve within it or just pass the instance.

aaronjensen
+4  A: 

Have you considered making the method an extension method? define it as

public static StaticExecute(this object instance)
{
    // reference to 'instance'
}

called like

this.StaticExecute();

I can't think of a way to do what you want to do directly, but can only suggest that if you find something, you watch out for static methods, which won't have one, and anonymous methods, which will have instances of auto-generated classes, which will be a little odd.

I do wonder whether you should just pass the invoking object in as a proper parameter. After all a static is a hint that this method doesn't depend on anything other than it's input parameters. Also note that this method may be a bitch to test, as any test code you write will not have the same invoking object as the running system.

Steve Cooper
A: 

I feel like I'm missing something, here. The static method can be called from literally anywhere. There's no guarantee that a class A or class B instance will appear anywhere in the call stack.

There's got to be a better way to accomplish whatever you're trying to do.

Mark Bessey
+1  A: 

In the case of a static method calling your static method, there is no calling instance.

Find a different way to accomplish whatever you are trying to do.

therealhoff
+1  A: 

I'm looking for the same possibility, the reason why is quite simple.

I have created an XNA-game which only uses bots for the gameplay (aka user can't really play himself). Ppl will be able to write bots that can be inserted in the game as a plug-in. Here's the thing, each bot has a function called Hit(Vector3 direction). Now, suppose someone would want to cheat (and we know ppl do), someone could just call Hit on sight, rather than shooting. So, I'm already using StackFrame to check whether the Hit was called by a Bullet (which is typically the only one allowed to call the Hit).

Now, I would like to sort of punish the bot that's cheating, by expelling him from the game, but to do that, I need to retrieve the instance to the bot calling Hit.