1

I need some solution to trace the class-owner of a method, in which the object is constructed. I mean to say, I want the constructor to automatically resolve the Type object of the "creator" class. Is it possible in C#?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ALOR
  • 545
  • 1
  • 9
  • 20

3 Answers3

3

An object doesn't naturally have any concept of a creator.

If you want to reliably determine what's creating an object, you'll need to express it explicitly in the constructor. Analysing stack frames not only has problems in low-trust environments (as Lasse mentioned) but can be inaccurate due to inlining.

What bigger problem are you trying to solve? Why is the class important to you? There may be a better approach.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thx for answer. I know that there is no such concept. It's not really big problem, but i was intrested, if it's possible. Here is the situation - i currently work with some old and not mine code. There are logging module, where i always should pass Type object of caller. It's not really needed, but useful for logger. So i wanted to resolve it by some code. – ALOR Aug 08 '09 at 14:01
  • I would personally pass in the appropriate type explicitly rather than using reflection. It's simpler, even if it's more verbose. – Jon Skeet Aug 08 '09 at 15:53
  • Eventually, so did i. I read some more about usage of stack trace, and found it ureliable with all this compiler-JIT-stuff. – ALOR Aug 08 '09 at 18:05
1

You can use the StackFrame to find out where the object was constructed from, but there are limitations to what it can figure out and when, for instance if you're running in some kind of lowered security mode, it won't be able to work.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
1

Assuming that inlining of the method that needs to check its caller and permissions aren't a problem, you can call the following method in a constructor:

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public static Type GetCallerType()
{
    StackTrace st = new StackTrace(2);
    StackFrame sf = st.GetFrame(0);
    return sf.GetMethod().DeclaringType;
}

So for your real question, the answer is yes, it is possible, but not recommended.

EDIT:

The method will require the reflection permission to access the GetMethod() method and the DeclaringType property. For the stack trace, a security permission for unmanaged code is needed (if I understand the documentation correctly), which basically renders this method useless for anything less than fully trusted code.

As you see, I decorated the method with an attribute that explicitly requests the JIT not to inline the method, since it walks at least one frame up the call stack. Problems arise if the calling method becomes inlined (or whatever transform the JIT applies) in its own calling method. I can give a sample with a short property, since properties are likely to be inlined by the JIT, though I cannot guarantee that this is corret:

public object PropertyThatGivesObject
{
    get { return new ObjectThatTracksItsCreator(); }
}

While this is pretty exotic (the property is not a 'property of an object', it is a factory), this has at least one problem:

  1. Is the property's declaring type really the creator (suppose it is an indirection)?
  2. If the property getter is inlined, should it have been the property's declaring type that was the creator? (Relevant if the method that invokes the property is declared by another type)
Cecil Has a Name
  • 4,962
  • 1
  • 29
  • 31
  • Thx. So, if i understood, i can get a wrong results, if caller method is inlined to some method of other class? And, please, can you be more descriptive about permissions problem? Any example please? – ALOR Aug 08 '09 at 14:46