471,325 Members | 1,269 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,325 software developers and data experts.

What class/method called my function?

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?

Dec 9 '05 #1
9 5806
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.

Dec 9 '05 #2
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).

Dec 9 '05 #3
So it needs to know the calling class... why?... to know which
configuration file to return? To know which struct to build?

Dec 9 '05 #4
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..

"Steve" <st**********@ticketmaster.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
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?

Dec 9 '05 #5
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().ReflectedTy pe,
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?

Dec 9 '05 #6
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.

Dec 9 '05 #7
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?

Dec 9 '05 #8
"Steve" <st**********@ticketmaster.com> a écrit dans le message de news:
11**********************@g43g2000cwa.googlegroups. com...

| 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

--
Joanna Carter [TeamB]
Consultant Software Engineer
Dec 12 '05 #9
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?".
*** Sent via Developersdex http://www.developersdex.com ***
Dec 24 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

28 posts views Thread by David MacQuigg | last post: by
24 posts views Thread by Xah Lee | last post: by
56 posts views Thread by Xah Lee | last post: by
21 posts views Thread by Helge Jensen | last post: by
4 posts views Thread by Rachel Suddeth | last post: by
18 posts views Thread by Xah Lee | last post: by
27 posts views Thread by Steven D'Aprano | last post: by
8 posts views Thread by Viktor | last post: by
13 posts views Thread by Hussein B | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.