4

I'm writing an ExceptionFactory class, using System.Diagnostics.StackTrace.

 var trace = new StackTrace(1, true);
 var frames = trace.GetFrames();
 var method =  frames[0].GetMethod();

Now, for classes

class Base
{
   public void Foo()
   {
      //Call ExceptionFactory from here
   }
} 
class A : Base {}

//...

var x = new A();
x.Foo();

method.DeclaringType would return typeof(Base). However, I need typeof(A). Is it possible to get somehow?

method.ReflectedType doesn't work either.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
TDaver
  • 7,164
  • 5
  • 47
  • 94
  • 3
    What exactly is an ExceptionFactory? – R. Martinho Fernandes Jan 31 '11 at 12:20
  • It parameterizes a custom exception based on the place of the calling (e.g.: Module, custom attributes on calling type, etc) - and this is why I need the actual type, so I can query class A for attributes instead of class Base – TDaver Jan 31 '11 at 12:24
  • Why doesn't ReflectedType work? What does it return? – Vlad Jan 31 '11 at 12:25
  • Base. Same as Declaring Type. – TDaver Jan 31 '11 at 12:26
  • 4
    @TDaver: just keep in mind that StackTrace may not contain all the frames you expect, as the JIT can optimize methods calls. – R. Martinho Fernandes Jan 31 '11 at 12:30
  • Yeah, I already had a question about that :) http://stackoverflow.com/questions/4849709/stack-trace-for-logging-in-net/4849946#4849946 – TDaver Jan 31 '11 at 12:36
  • 1
    Martinho is correct. And apart from this, getting parameters from stack frames is not really possible in a generic way, so that you'll likely not be able to achieve what you want. This is especially true for release builds. See also: http://stackoverflow.com/questions/75076/obtain-parameter-values-from-stackframe-in-net – Lucero Jan 31 '11 at 12:37

2 Answers2

4

No, since the method is actually declared on Base. As long as the method is not overridden, you always get the same MethodInfo instance for the method independent of whether you query it on the base class or on the derived class.

But why do you need the other type in the first place? There may be another solution to your problem, that's why I'm asking this.

Lucero
  • 59,176
  • 9
  • 122
  • 152
  • My base class contains basic operations (like delete, insert, etc). If anything is faulty, I want to raise an exception, with finding out the operation type (insert,delete,etc), layer (business logic, data access ,etc), and module of the location of the error. However if the problem is in class A, which is in module "Project1", and base is in "Framework", I want the module to be "Project1", but since the exception was raised in Base, I'll get "Framework"... – TDaver Jan 31 '11 at 12:35
  • If the members defined in the "Framework" are virtual or abstract and then overridden by the "Project1" classes, you'll get the information you want... – Lucero Jan 31 '11 at 12:40
  • I've decided that on non-overriden cases, I'll provide the exceptionFactory with the required data (Module and actual ClassName) myself. If none provided, it will search the StackTrace. – TDaver Jan 31 '11 at 12:48
0

Yeah, just use this.GetType(). That will return the subclass. So the following code snippet should print "A".

public void Foo()
{
    System.Diagnostics.Debug.Print(this.GetType().ToString());
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jack Allan
  • 14,554
  • 11
  • 45
  • 57
  • 2
    From my understanding, the `ExceptionFactory` is a separate class which relies on the stack trace to generate the exception; so it is likely that there is no "this" available. – Lucero Jan 31 '11 at 12:30
  • Exactly, although if there are no other solutions it will take a Type parameter (however that wouldn't be very nice, because it will only correspond with the first level of the trace, so it's not a global solution...) – TDaver Jan 31 '11 at 12:32
  • This will work *as long as you are inside the method* or at least within the same type. When you make a call to a method within another type, this will (obviously) no longer be an option, regardless of whether the invoked helper method is static or not. – Fredrik Mörk Jan 31 '11 at 12:36
  • @TDaver could you not pass in "this" to the ExceptionFactory constructor? – Jack Allan Jan 31 '11 at 13:03
  • ExceptionFactory is static, there was no reason to create a new instance just for one "throw"... – TDaver Jan 31 '11 at 13:29
  • @TDaver I don't think it's possible in that case using StackTrace. You could use some unsafe code to try to unpeel the stack but as Martinho commented above you will get all sorts of things missing in the stack as a result of JIT optimization. – Jack Allan Jan 31 '11 at 14:31