c# – 复合应用程序的最佳日志记录方法?

前端之家收集整理的这篇文章主要介绍了c# – 复合应用程序的最佳日志记录方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在创建一个具有多个不同项目( Shell,模块等)的复合WPF(Prism)应用程序.我已经准备好使用Log4Net实现日志记录.看来有两种方法来设置日志记录:

>让Shell项目执行所有的实际日志记录.它获得对Log4Net的引用,其他项目会启动复合事件,让Shell知道它需要记录某些东西.这些项目仅在Shell的app.config文件(DEBUG,ERROR等)中打开日志记录的级别引发事件,以免降低性能.
>给每个项目,包括模块,一个Log4Net引用,并让项目自己的日志记录到一个通用的日志文件,而不是发送消息到Shell进行日志记录.

哪种更好的方法?或者,是否有另一种方法我应该考虑?谢谢你的帮助.

解决方法

登录Prism的最简单的方法是覆盖Bootstrapper中的LoggerFacade属性.通过重写LoggerFacade,只要记录器实现ILoggerFacade接口,就可以传递任何需要的任何Logger的Logger实例.

我发现以下内容在日志记录方面工作得很好(我正在使用Enterprise Libary Logging块,但应用类似于Log4Net的应该是直接的):

在你的Shell中创建一个Boostrapper:

  1. -My Project
  2. -Shell Module (add a reference to the Infrastructure project)
  3. -Bootstrapper.cs

在基础架构项目中创建日志记录适配器,即:

  1. -My Project
  2. -Infrastructure Module
  3. -Adapters
  4. -Logging
  5. -MyCustomLoggerAdapter.cs
  6. -MyCustomLoggerAdapterExtendedAdapter.cs
  7. -IFormalLogger.cs

MyCustomLoggerAdapter类将用于覆盖Bootstrapper中的“LoggerFacade”属性.它应该有一个默认的构造函数来消息一切.

注意:通过覆盖Bootstrapper中的LoggerFacade属性,您正在为Prism提供一种日志记录机制,用于记录其自己的内部消息.您可以在整个应用程序中使用此记录器,也可以扩展记录器以获取更全面的记录器. (请参阅MyCustomLoggerAdapterExtendedAdapter / IFormalLogger)

  1. public class MyCustomLoggerAdapter : ILoggerFacade
  2. {
  3.  
  4. #region ILoggerFacade Members
  5.  
  6. /// <summary>
  7. /// Logs an entry using the Enterprise Library logging.
  8. /// For logging a Category.Exception type,it is preferred to use
  9. /// the EnterpriseLibraryLoggerAdapter.Exception methods."
  10. /// </summary>
  11. public void Log( string message,Category category,Priority priority )
  12. {
  13. if( category == Category.Exception )
  14. {
  15. Exception( new Exception( message ),ExceptionPolicies.Default );
  16. return;
  17. }
  18.  
  19. Logger.Write( message,category.ToString(),( int )priority );
  20. }
  21.  
  22. #endregion
  23.  
  24.  
  25. /// <summary>
  26. /// Logs an entry using the Enterprise Library Logging.
  27. /// </summary>
  28. /// <param name="entry">the LogEntry object used to log the
  29. /// entry with Enterprise Library.</param>
  30. public void Log( LogEntry entry )
  31. {
  32. Logger.Write( entry );
  33. }
  34.  
  35. // Other methods if needed,i.e.,a default Exception logger.
  36. public void Exception ( Exception ex ) { // do stuff }
  37. }

MyCustomLoggerAdapterExtendedAdapter是从MyCustomLoggerAdapter导出的,可以为更加完整的记录器提供其他构造函数.

  1. public class MyCustomLoggerAdapterExtendedAdapter : MyCustomLoggerAdapter,IFormalLogger
  2. {
  3.  
  4. private readonly ILoggingPolicySection _config;
  5. private LogEntry _infoPolicy;
  6. private LogEntry _debugPolicy;
  7. private LogEntry _warnPolicy;
  8. private LogEntry _errorPolicy;
  9.  
  10. private LogEntry InfoLog
  11. {
  12. get
  13. {
  14. if( _infoPolicy == null )
  15. {
  16. LogEntry log = GetLogEntryByPolicyName( LogPolicies.Info );
  17. _infoPolicy = log;
  18. }
  19. return _infoPolicy;
  20. }
  21. }
  22.  
  23. // removed backing code for brevity
  24. private LogEntry DebugLog... WarnLog... ErrorLog
  25.  
  26.  
  27. // ILoggingPolicySection is passed via constructor injection in the bootstrapper
  28. // and is used to configure varIoUs logging policies.
  29. public MyCustomLoggerAdapterExtendedAdapter ( ILoggingPolicySection loggingPolicySection )
  30. {
  31. _config = loggingPolicySection;
  32. }
  33.  
  34.  
  35. #region IFormalLogger Members
  36.  
  37. /// <summary>
  38. /// Info: informational statements concerning program state,/// representing program events or behavior tracking.
  39. /// </summary>
  40. /// <param name="message"></param>
  41. public void Info( string message )
  42. {
  43. InfoLog.Message = message;
  44. InfoLog.ExtendedProperties.Clear();
  45. base.Log( InfoLog );
  46. }
  47.  
  48. /// <summary>
  49. /// Debug: fine-grained statements concerning program state,/// typically used for debugging.
  50. /// </summary>
  51. /// <param name="message"></param>
  52. public void Debug( string message )
  53. {
  54. DebugLog.Message = message;
  55. DebugLog.ExtendedProperties.Clear();
  56. base.Log( DebugLog );
  57. }
  58.  
  59. /// <summary>
  60. /// Warn: statements that describe potentially harmful
  61. /// events or states in the program.
  62. /// </summary>
  63. /// <param name="message"></param>
  64. public void Warn( string message )
  65. {
  66. WarnLog.Message = message;
  67. WarnLog.ExtendedProperties.Clear();
  68. base.Log( WarnLog );
  69. }
  70.  
  71. /// <summary>
  72. /// Error: statements that describe non-fatal errors in the application;
  73. /// sometimes used for handled exceptions. For more defined Exception
  74. /// logging,use the Exception method in this class.
  75. /// </summary>
  76. /// <param name="message"></param>
  77. public void Error( string message )
  78. {
  79. ErrorLog.Message = message;
  80. ErrorLog.ExtendedProperties.Clear();
  81. base.Log( ErrorLog );
  82. }
  83.  
  84. /// <summary>
  85. /// Logs an Exception using the Default EntLib Exception policy
  86. /// as defined in the Exceptions.config file.
  87. /// </summary>
  88. /// <param name="ex"></param>
  89. public void Exception( Exception ex )
  90. {
  91. base.Exception( ex,ExceptionPolicies.Default );
  92. }
  93.  
  94. #endregion
  95.  
  96.  
  97. /// <summary>
  98. /// Creates a LogEntry object based on the policy name as
  99. /// defined in the logging config file.
  100. /// </summary>
  101. /// <param name="policyName">name of the policy to get.</param>
  102. /// <returns>a new LogEntry object.</returns>
  103. private LogEntry GetLogEntryByPolicyName( string policyName )
  104. {
  105. if( !_config.Policies.Contains( policyName ) )
  106. {
  107. throw new ArgumentException( string.Format(
  108. "The policy '{0}' does not exist in the LoggingPoliciesCollection",policyName ) );
  109. }
  110.  
  111. ILoggingPolicyElement policy = _config.Policies[policyName];
  112.  
  113. var log = new LogEntry();
  114. log.Categories.Add( policy.Category );
  115. log.Title = policy.Title;
  116. log.EventId = policy.EventId;
  117. log.Severity = policy.Severity;
  118. log.Priority = ( int )policy.Priority;
  119. log.ExtendedProperties.Clear();
  120.  
  121. return log;
  122. }
  123.  
  124. }
  125.  
  126.  
  127. public interface IFormalLogger
  128. {
  129.  
  130. void Info( string message );
  131.  
  132. void Debug( string message );
  133.  
  134. void Warn( string message );
  135.  
  136. void Error( string message );
  137.  
  138. void Exception( Exception ex );
  139.  
  140. }

在Bootstrapper中:

  1. public class MyProjectBootstrapper : UnityBootstrapper
  2. {
  3.  
  4. protected override void ConfigureContainer()
  5. {
  6. // ... arbitrary stuff
  7.  
  8. // create constructor injection for the MyCustomLoggerAdapterExtendedAdapter
  9. var logPolicyConfigSection = ConfigurationManager.GetSection( LogPolicies.CorporateLoggingConfiguration );
  10. var injectedLogPolicy = new InjectionConstructor( logPolicyConfigSection as LoggingPolicySection );
  11.  
  12. // register the MyCustomLoggerAdapterExtendedAdapter
  13. Container.RegisterType<IFormalLogger,MyCustomLoggerAdapterExtendedAdapter>(
  14. new ContainerControlledLifetimeManager(),injectedLogPolicy );
  15.  
  16. }
  17.  
  18. private readonly MyCustomLoggerAdapter _logger = new MyCustomLoggerAdapter();
  19. protected override ILoggerFacade LoggerFacade
  20. {
  21. get
  22. {
  23. return _logger;
  24. }
  25. }
  26.  
  27. }

最后,要使用任何一个记录器,您需要做的就是将适当的接口添加到类的构造函数中,并且UnityContainer将为您注入记录器:

  1. public partial class Shell : Window,IShellView
  2. {
  3. private readonly IFormalLogger _logger;
  4. private readonly ILoggerFacade _loggerFacade;
  5.  
  6. public Shell( IFormalLogger logger,ILoggerFacade loggerFacade )
  7. {
  8. _logger = logger;
  9. _loggerFacade = loggerFacade
  10.  
  11. _logger.Debug( "Shell: Instantiating the .ctor." );
  12. _loggerFacade.Log( "My Message",Category.Debug,Priority.None );
  13.  
  14. InitializeComponent();
  15. }
  16.  
  17.  
  18. #region IShellView Members
  19.  
  20. public void ShowView()
  21. {
  22. _logger.Debug( "Shell: Showing the Shell (ShowView)." );
  23. _loggerFacade.Log( "Shell: Showing the Shell (ShowView).",Priority.None );
  24. this.Show();
  25. }
  26.  
  27. #endregion
  28.  
  29. }

我不认为你需要一个单独的模块用于日志策略.通过将日志记录策略添加到基础架构模块,所有其他模块将获得所需的引用(假设您将基础架构模块添加为其他模块的参考).通过将Logger添加到Boostrapper,您可以让UnityContainer根据需要注入日志记录策略.

CodePlex上的CompositeWPF contrib项目还有一个simple example of uisng Log4Net.

HTH的

猜你在找的C#相关文章