page 1 of 2
Comments: 28 | Views: 3841
ScanIAm
ScanIAm
On a scale of 1 to 10, people are stupid.
I'm trying to come up with some code that I can use to add INFO level tracing to my DAL and BL code.  So far, I'm able to obtain plenty of metadata about the functions, but not the actual parameter values:

StringBuilder sb = new StringBuilder();

sb.Append(System.Reflection.MethodBase.GetCurrentMethod());

ParameterInfo [] ParameterInfos = System.Reflection.MethodBase.GetCurrentMethod().GetParameters();

foreach (ParameterInfo ParameterInfo in ParameterInfos)

sb.Append(" ").Append(ParameterInfo.Name).Append(" {").Append(ParameterInfo).Append("}");

TraceLog.Info(sb.ToString());



this will output the metadata about the parameters, but not the actual values.  For example, it will show me that the value is an Int32, but not that the value is 3.

I know that this is doable, but I can't seem to pick the right combination of words, punctuation, and secret masonic dances required to get Google to return a clue.

Any clues?

Edit: oh, and what the heck is the 'code' tag on C9 again?

littleguru
littleguru
<3 Seattle
You can't get them via reflection. Reflection works on the meta-data that has been embedded during compilation... Your best bet would be sending them in manually...
StackTrace
StackFrame

Try inspecting the call stack with System.Diagnostics classes?  Though I can't find the methods to crack the parameters.  If you find the answer to your question, please post it here!

yeah .NET API doesn't contains anything wich would help you to do that, there is Debugging API, maybe it can help you? i'll give it a try
PerfectPhase
PerfectPhase
"This is not war, this is pest control!" - Dalek to Cyberman
Ion Todirel wrote:
yeah .NET API doesn't contains anything wich would help you to do that, there is Debugging API, maybe it can help you? i'll give it a try


How does something like RhinoMocks manage to record the parameters passed into a method call?

EDIT: You could do sort of do this with DynamicProxies
littleguru
littleguru
<3 Seattle
ScanIAm wrote:

Ion Todirel wrote: yeah .NET API doesn't contains anything wich would help you to do that, there is Debugging API, maybe it can help you? i'll give it a try


I'll take a look at that tomorrow, too.  It seems that if the serializer classes can do this with an object, that it should be doable for method parameters.

It sure would make tracing a bit easier.

Thanks, all, for the input.


The serializer uses GetProperties on the type and then GetValue on each property. That's easy and that is doable. But the getting of parameter values is another story and not so easy to do.

There is a Debugger API - that's also implemented by the debugger - to get the values, but that is another pair shoes and harder to do... I don't know if that API is also available when you ship the product or comes only with VS!

You could go the easy way and send the arguments in - like in the order they appear in the method and assign them manually. It is not so nice, but would do it...
Sven Groot
Sven Groot
My name has 9 letters. Coincidence? I think not...
As far as I know there is no way to do this without using debugger APIs or something. We've had a thread about this in the Techoff before, it went nowhere then too.
littleguru
littleguru
<3 Seattle
ScanIAm wrote:
This is proving to be much more difficult that I thought.

The weird thing, is that I can gain access to a ParameterInfo which contains the attribute 'name' as well as it's type.  I just can't figure out how to make .NET evaluate it Sad


The ParameterInfo class comes directly from the metadata. It is part of the metadata that has been embedded for that class... You can get the properties also because the metadata is used to gain access to the class that you want to get the data from. The problem with parameters is that they don't exist in the class - they exist only on the stack for a given time... It's a completely different situation and has nothing to do with reflection - as it is implemented right now.
littleguru
littleguru
<3 Seattle
ScanIAm wrote:

littleguru wrote: 
ScanIAm wrote: This is proving to be much more difficult that I thought.

The weird thing, is that I can gain access to a ParameterInfo which contains the attribute 'name' as well as it's type.  I just can't figure out how to make .NET evaluate it Sad


The ParameterInfo class comes directly from the metadata. It is part of the metadata that has been embedded for that class... You can get the properties also because the metadata is used to gain access to the class that you want to get the data from. The problem with parameters is that they don't exist in the class - they exist only on the stack for a given time... It's a completely different situation and has nothing to do with reflection - as it is implemented right now.


It's just so frustrating Smiley  I can almost 'see' the solution, but I get stymied at every avenue.

I went through some of the Type.Invoke code to see if that would work, but again, you need to somehow get access to the actual objects themselves.

The would surely be a nice 'feature' to add to the next version of .Net.


It's how the system is build. if you look at it it is a stack machine. It is way complexer to fetch the data because it is not in a type or so... it's in the code... it's no member data at all. It's put dynamically on the stack and then the method is called.
RichardRudek
RichardRudek
So what do you expect for nothin'... :P
I am not an expert. But it seems to me that your having some kind of mental block on this. That is, you appear to confusing your "cake recipe" with an actual cake.

As has already been mentioned, by the time your within an exception block, about the only thing left for you to do is to try and scrounge up whats left by trolling though the stack. ie the Debugging APIs.

About the only other way that I can think of is if you force all of your routines to use globals variables rather than parameters. As has already been mentioned, these parameters live on the stack, not on the heap (globals). And debuggers use the debugging APIs.

As for the ASP bind/eval stuf, I doubt your perception. Remember, your looking for the actual passed in parameters - the cake.

littleguru
littleguru
<3 Seattle
ScanIAm wrote:

RichardRudek wrote:
As for the ASP bind/eval stuf, I doubt your perception. Remember, your looking for the actual passed in parameters - the cake.



Yes, exactly.  For example, if I'm displaying a gridview, and using an ObjectDataSource, the only thing I need to tell the GridView is the 'name' of the return object.  It is able to take that 'name' and the Type and end up with the value found inside that variable.

In this case, I have the name and type of the parameters, but no way to get .NET to evaluate the parameter (like the GridView does). 


That's still only fetching property values from an instance of a class where you get the data from that instance. As said to get the parameter values is different. I don't say they should implement a way to get them, because it would be neath in certain scenarios, but they didn't...
RichardRudek
RichardRudek
So what do you expect for nothin'... :P
ScanIAm wrote:

RichardRudek wrote:I am not an expert. But it seems to me that your having some kind of mental block on this. That is, you appear to confusing your "cake recipe" with an actual cake.

The cake is a lie.

No, at the moment, your looking at the cake over a webcam - you need to travel over to where the actual cake is... Wink

ScanIAm wrote:

RichardRudek wrote:
As has already been mentioned, by the time your within an exception block, about the only thing left for you to do is to try and scrounge up whats left by trolling though the stack. ie the Debugging APIs.

This wouldn't be in an exception condition, but yep, someone did mention using the Debugging APIs.  I just haven't had a chance to look at them yet. 

Run, don't walk...Smiley
ScanIAm wrote:

RichardRudek wrote:
About the only other way that I can think of is if you force all of your routines to use globals variables rather than parameters. As has already been mentioned, these parameters live on the stack, not on the heap (globals). And debuggers use the debugging APIs.

But, .NET operates differently than an unmanaged app.  There aren't any INT13 calls to be made, because the CLR is processing and interpreting the IL.  It can stop any time it wants to whereas an unmanaged app needs to force the CPU to be interrupted.

Ah, and therein lies your mental block.

Here's a question, what does JIT'ing do ?

BTW, just to be pedantic, it's INT 3. INT 13, depending upon whether your decimal or hex is either a General protection fault/exception, or BIOS disk I/O... Wink

ScanIAm wrote:

RichardRudek wrote:
As for the ASP bind/eval stuf, I doubt your perception. Remember, your looking for the actual passed in parameters - the cake.


Yes, exactly.  For example, if I'm displaying a gridview, and using an ObjectDataSource, the only thing I need to tell the GridView is the 'name' of the return object.  It is able to take that 'name' and the Type and end up with the value found inside that variable.

In this case, I have the name and type of the parameters, but no way to get .NET to evaluate the parameter (like the GridView does).

Yes, you have the cake receipe. The actual data is on the stack (in the current stack-frame). The original source of that data, before it was parametised, may also be on the stack (in an earlier stack-frame), or it may be on the heap.

You know those stack traces you see when your debugging ?

Well guess what, to produce those, and the local variables stuff, requires some rather "heavy magic" (good some Sam). And where is this magic ?

Well it's likely to be in the debugging API's. I have don't know for certain because I've not had the need to go look. Whereas you appear to, so go ahead...Smiley

Is this "magic" perfect ?

No. I don't know for about Managed code, but I often see the Stack traces which have warnings to the effect that, what you see beyond this point in the stack trace is my best guess, so caution.

ScanIAm wrote:
 There has to be some behind-the-scenes magic going on to allow the Bind or Eval functions to obtain the values of an object based solely on the name and type of the object, so why can't I do this?


Yes, there will be "instance tables", metadata which is probably incorporated with the Garbage Collector. But I suspect that they would have optimised what is tracked. ie data on the stack is a completely different proposition than data in what I call the heap. I'm not sure such terminology is correct for Managed code, but I don't see point if it's not.

You have to remember that when you pass stuff via parameters, space is made for it (or a reference to it) on the stack. From a debugging point of view, the data is in a different stack-frame. Each time you enter a new routine, and I believe that also includes the processing of an exception, a new stack-frame is setup. To decode this resulting stack (which contains multiple stack-frames) is a tricky business. There'll be return addresses, saved registers, and locals such as parameters and local variables in each stack frame. That's the magic.
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
RichardRudek wrote:

ScanIAm wrote:
RichardRudek wrote:I am not an expert. But it seems to me that your having some kind of mental block on this. That is, you appear to confusing your "cake recipe" with an actual cake.

The cake is a lie.

No, at the moment, your looking at the cake over a webcam - you need to travel over to where the actual cake is...


Can we stop with the cake analogy. It confuses me more than the original problem.

Also it reminds me of this comic strip.
RichardRudek
RichardRudek
So what do you expect for nothin'... :P
evildictaitor wrote:

Can we stop with the cake analogy. It confuses me more than the original problem.


Ha ha. Yes, if the novice is providing the analogy, then I agree. Given that I'm not an expert, then, fine...Wink

But just to clarify:

cake recipe == IL, perhaps source code.
cake == JIT'd code and current execution state.
webcam == reflection (aparently)
debug API == um, nasty Smiley
Minh
Minh
WOOH! WOOH!
This is what I'm currently doing (going off memory here):

...
void MyFunc(string name, int age, Gender gender)
{
   FuncInfo fi = new FuncInfo("MyFunc", name, age, gender);
   Logger.Log(fi);
   ...
}
...

class FuncInfo
{
   public FuncInfo(string funcName, param object[] paramValues)
   {
      _funcName = funcName;

      _paramValues = new string[paramValues.Length];
      for (int i = 0; i < paramValues.Length; i++)
      {
         _paramValues[i] = paramValues[i].ToString();
      }    
   }

   public override string ToString()
   {
      // Implement how you want it logged here
   }

   string _funcName;
   string[] _paramValues;
}
littleguru
littleguru
<3 Seattle
This is what I meant with passing the stuff in manually.
page 1 of 2
Comments: 28 | Views: 3841
Microsoft Communities