0

I'm not quite sure how best ask this question, so please feel free to edit...

I have a "Utilities" class that contains common functionality used throughout my application. One of my methods logs exeptions like this:

internal static void logExeption(Type typeOfClass, string methodName, Exception exeption )
 {
   //Do some logging here
 }

Then I'd like to call it throughout my application whenever I catch an exception like so:

try{
  //perform some action
}
catch(Exception ex)
{
Utils.logExeption(this.GetType(), System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
 }

I would like to know if there's a way I can avoid passing in the first two parameters and just figure out the context of the Class/Method where the exception originated right in the logException method. This will make things cleaner for me in the long run.

4

3 に答える 3

4

したがって、呼び出し元のオブジェクトと関数を決定する必要があります。推奨されていませんが、達成できます。System.Diagnostics.StackTraceを使用してスタックをウォークします。次に、適切なStackFrameを1レベル上に移動します。次に、そのStackFrameでGetMethod()を使用して、どのメソッドが呼び出し元であるかを判別します。スタックトレースの構築は潜在的にコストのかかる操作であり、メソッドの呼び出し元が実際にどこから来ているのかを不明瞭にする可能性があることに注意してください。

StackFrame frame = new StackFrame(1);
MethodBase method = frame.GetMethod();
string message = String.Format("{0}.{1} : {2}",
method.DeclaringType.FullName, method.Name, message);
Console.WriteLine(message);
于 2012-08-02T17:02:35.637 に答える
2

Please note that frame.GetMethod().DeclaringType can return null: sometime ago I faced with this problem only on release build of my application using NLog logger (GetCurrentClassLogger). Can't remember exactly the case. By the way, it is known issue.

There is an interesting trick in Apache log4net which allows to detect the caller info (class, method, etc.).

Please take a look at:

  1. LocationInfo class (source) - the internal representation of caller location information.

     public class LocationInfo
     {
         ...
    
         public LocationInfo(Type callerStackBoundaryDeclaringType)
         {
             // Here is the trick. See the implementation details here.
         }
    
         ...
     }
    
  2. LogImpl class (source) - the logger implementation class - wrapper around ILogger interface - to do the trick it must not be subclassed!

     public class LogImpl : LoggerWrapperImpl, ILog
     {
         ...
         public LogImpl(ILogger logger) : base(logger)
         {
             ...
         }
    
         /// <summary>
         /// The fully qualified name of this declaring type not the type of any subclass.
         /// </summary>
         private readonly static Type ThisDeclaringType = typeof(LogImpl);
    
         virtual public void Error(object message, Exception exception)
         {
             Logger.Log(ThisDeclaringType, m_levelError, message, exception);
         }
    
         ...
     }
    
于 2012-08-02T17:54:56.380 に答える
0

You can use StackTrace Class. See the example there which is very similar with your question.

于 2012-08-02T17:03:06.903 に答える