I've created wrapper for logging library inside of which I want to log parameters of the outer method that thrown exception:
public void MethodA(string param1, int param2)
{
try
{
throw new Exception();
}
catch(Exception ex)
{
Logger.Error(ex);
}
}
...
public static void Error(Exception ex)
{
...
}
As you can see I would like to get MethodA informations on the Error method level. I would be more than happy just to use:
ParameterInfo[] pi = new StackFrame(1).GetMethod().GetParameters();
because it has everything, but I just read multiple SO posts about poor performance. Seems to me that maybe it's not the best way then (on the other hand, we're talking about exception handling - at this point of time it's already not too important). However, I cannot find traditional approach using Reflection to solve this. Perhaps someone can enlighten me?
Or maybe you would still go with StackFrame solution ? It's asp.net application with rather small demands for ultra performance.
Edit1: Maybe I was not so sure what I want to write. I AM going with StackFrame solution even if it can take up to 20 ms to get a frame but I am really curious how to get similiar result with reflection.
You might find this utility method of mine useful, since it also solves another problem which you are likely to come across: things are a bit weird when you want to get the current stack frame from within a constructor.
(Note:
Collections.Util.NewListReadonly()
is a static utility method of mine which creates a read-only list and returns itsIList<T>
interface.)I do not know about the performance of
new Diagnostics.StackTrace()
: I would guess that it is as slow as using reflection, (it probably counts as reflection,) but probably a bit faster than throwing an exception.I will disappoint you about the parameters part though: I have found no way to obtain the contents of parameters to methods at runtime. So, all that you can hope to get is the types and names of the parameters, but not their values. If you find a way, please let me know.
There are a few different aspects to this question:
You can use an interception-based technique built off your favorite IoC container, but I've honestly found the best approach is usually just to pass the parameters into the exception information:
From what I can gather, you're only ever planning to use this to log an error when an exception is thrown. In that case, I'd just stick with your StackFrame-based solution for the time being, since it's unlikely to occur very often. When C# 5 comes out, you'll be able to use the
[CallerMemberName]
attribute:A word to the wise
It's good practice to limit the number of places where you catch exceptions like this. Generally it's best just to let the exception pass itself up the chain until the last possible moment, where you can gracefully tell the user something unexpected happened and log the error at that point. This gives you a much more informative stacktrace on the Exception itself. If you want to pass additional information along at some point along the way, just wrap the exception in an inner exception and throw that:
None of these. I would go with an interception solution using something like Castle Windsor. Then it's very easy to get the parameters to the method that was intercepted.
I would go with this approach so long as you use exceptions only in error conditions, not as a "return value" of a method. (See Exceptions vs. Return Values). If you don't throw a lot of exceptions -- and most applications don't -- then you'll be fine.
Our group writes trading software that we heavily monitor for performance. So long as the thrown exceptions don't occur in a critical path you're fine. Usually, if an unhandled exception is thrown then performance isn't relevant: the user isn't waiting for a response. Or that response won't arrive because of the exception.
Note that you may want to do an index check before using a hard-coded new StackFrame(1).