What class/method called my function?

S

Steve

Hello --

I've been struggling with this problem for over a day now. I'd like to
know (without passing parameters) which class, and preferably, which
method of that class has called my function.

I can get the calling assembly rather easily, but let's say within
Assembly X I have

class A
class B
class C

I'd like to know that in Assembly X, Class C, Method callFunction() has
invoked my function.

So, use the StackTrace and StackFrame classes, right? A bit of a
problem when it comes to the release build. I also am not fond of
deploying .pdb files out to production.

The StackTrace and Frame work perfectly in debug mode.. however, in the
release build, either the compiler optimizes or something, since it
tends to "skip" my calling function, and goes to the one before it. Ex
(Desired trace ran in debug mode)

WhoIsKnocking()
callFunction()
button1_onclick()

in release builds, I get

WhoIsKnocking()
button1_onclick()

I find it hard to believe that no information is given about the stack
in a release build. Or reflection does not allow to find out the
calling object. I'm using .Net 2.0.

Am I missing something basic, or is there another class/package out
there that I haven't looked at yet?
 
B

Bruce Wood

Why do you need to know "who" is calling your method? Perhaps there is
another design for what you're trying to do that doesn't involve stack
walking magic.
 
S

Steve

Thanks for responding.

Basically I'm looking to load member level variables from a
configuration file into the calling class. So this function that is
being called, loads up a struct based on a configuration/xml file, and
returns the struct to the calling class. (I asked for function name as
well, since I'll probably use that for something else later).
 
B

Bruce Wood

So it needs to know the calling class... why?... to know which
configuration file to return? To know which struct to build?
 
R

RCS

What about giving your provider class a string parameter in the constructor,
that way, in your logging, any subsequent calls could be tracked now only by
who, but by "session" almost too... In other words:

SomeProvider sp = new SomeProvider("CallingObject - my name is Bob",
SessionID);
sp.DoSomething();
sp.ImportantMethod();

Just a thought..
 
S

Steve

Thanks guys.

For the first question, *kinda* want to know which config file to
return. More like config section. So AssemblyA_dll.config will
contain

<className='a'>
<var name="x" value="2"
</className>
<className='b'>

and so forth.

RCS -- I did look that route. I find it kinda "clunky". What's I'm
trying to do is to make a central configuration reader that resides in
the GAC. I know each class can use a config reader, but there are
other reasons I'd like to have a central point of location.

I can do

MyConfig c = new MyConfig(MethodBase.GetCurrentMethod().ReflectedType,
MethodBase.GetCurrentMethod);

I was thinking a more eloquent way is to have the receiving class
"know" who is calling. That way, the MyConfig can scale a lot better
across different projects.

I would think as well that the stack trace *has* to stay intact
somehow, since the Exception class uses it, even for release builds?
Exception knows the stack... how come I can't find an exposed class (or
another method) that does the same?
 
B

Bruce Wood

OK... I think I get the picture now. First, some comments on your
proposed design.

If you have your configuration reader look at the stack trace to see
"who" is calling, and then select the configuration section based on
that, you would likely have to change your configuration reader every
time you introduce a new client, unless you "hard-wire" the name of the
configuration section to the name of the calling class, or something
ugly like that. Otherwise, every time you add a new caller, you have to
add code to your configuration reader that says, "Caller X needs
configuration section Y." Not nice.

I've done similar stuff with the Registry. I suggest that you try this
instead:

public interface IHasConfigurationSection
{
string ConfigurationSectionName { get; }
void ReadConfigurationSection( ... );
}

Then have every caller that wants to read a configuration section
implement this interface. Then, when you call your configuration
reader, you call it like this:

ConfigurationReader.ReadConfiguration(this);

where the ReadConfiguration method is declared like this:

public static ReadConfiguration(IHasConfigurationSection client)
{ ... }

The configuration reader will then call your object ("this") back,
first to get the ConfigurationSectionName, then to call the
ReadConfigurationSection() method so that your object can extract the
necessary information from the configuration section.

I left the arguments to ReadConfigurationSection() out because that's
part of your design problem: what's the easiest way for your class to
receive the config information? For example, in the case of my Registry
reader, I pass the class a Hashtable that has config entry names as
keys and the values against those entries as hashed values. However,
you may be storing more sophisticated constructs and so may need
something more complex than that.

As well, in my classes I have a WriteConfiguration method, and a
corresponding WriteConfigurationSection() method in the interface.
Again, I call it like this:

ConfigurationReader.WriteConfiguration(this);

and the ConfigurationReader calls my object back to get the information
to store (in my case, in the Registry) and the configuration section
name (in my case the Registry key).

This would make your configuration reader stable... it would never need
to be changed. The only requirement would be that calling classes need
to implement the correct interface, but then that information would
need to be encoded somewhere, anyway.

No stack walks necessary.
 
S

Steve

Thanks Bruce --

My first look at this task was to use an interface. Basically it was
the same as what you're doing here. Even down to the hashtable :)

However, this one class I'm trying to write is going to be centralized
around hundreds of other classes that use it. Nearly every class in
every project will use it. I'm also leaving out some other details for
clarity, but this configuration class loads a lot more than just the
configSections. But yes, for the beginning, the class name will be
hardwired to the calling class' name. That's pretty much why I wanted
to know "who" was calling me :) The stack trace just made the most
sense.

Is what I'm asking not possible in 2.0? Or is it possible, but .Net
doesn't expose any of this functionality to us?
 
J

Joanna Carter [TeamB]

"Steve" <[email protected]> a écrit dans le message de (e-mail address removed)...

| I've been struggling with this problem for over a day now. I'd like to
| know (without passing parameters) which class, and preferably, which
| method of that class has called my function.
|
| Am I missing something basic, or is there another class/package out
| there that I haven't looked at yet?

This kind of question come up often and is an indication of poor program
design.

If you really have to know what is calling a method, then add a parameter to
the method so that you can pass the sender. See how the EventHandler
delegate class does this.

Joanna
 
D

d webster

Change GetFrame() index (within bounds) & explore the stack.

public void CallingObjectAndMethod()
{
StackTrace ST = new StackTrace();
StackFrame SF = ST.GetFrame(1); // <-- 0, 1, 2 ...
MethodBase MB = SF.GetMethod();

string methodName = MB.Name;
string objectName = MB.DeclaringType.Name;

MessageBox.Show(objectName + methodName);
}

public void WhatAmI()
{
string temp = this.GetType().ToString();

MessageBox.Show(temp);
}

Don't be surprised if things look different under the hood than
expected. Hope this helps you get started.

- webster -

Thanks for providing solutions without asking "Why?".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top