>让Shell项目执行所有的实际日志记录.它获得对Log4Net的引用,其他项目会启动复合事件,让Shell知道它需要记录某些东西.这些项目仅在Shell的app.config文件(DEBUG,ERROR等)中打开日志记录的级别引发事件,以免降低性能.
>给每个项目,包括模块,一个Log4Net引用,并让项目自己的日志记录到一个通用的日志文件,而不是发送消息到Shell进行日志记录.
解决方法
我发现以下内容在日志记录方面工作得很好(我正在使用Enterprise Libary Logging块,但应用类似于Log4Net的应该是直接的):
在你的Shell中创建一个Boostrapper:
- -My Project
- -Shell Module (add a reference to the Infrastructure project)
- -Bootstrapper.cs
在基础架构项目中创建日志记录适配器,即:
- -My Project
- -Infrastructure Module
- -Adapters
- -Logging
- -MyCustomLoggerAdapter.cs
- -MyCustomLoggerAdapterExtendedAdapter.cs
- -IFormalLogger.cs
MyCustomLoggerAdapter类将用于覆盖Bootstrapper中的“LoggerFacade”属性.它应该有一个默认的构造函数来消息一切.
注意:通过覆盖Bootstrapper中的LoggerFacade属性,您正在为Prism提供一种日志记录机制,用于记录其自己的内部消息.您可以在整个应用程序中使用此记录器,也可以扩展记录器以获取更全面的记录器. (请参阅MyCustomLoggerAdapterExtendedAdapter / IFormalLogger)
- public class MyCustomLoggerAdapter : ILoggerFacade
- {
- #region ILoggerFacade Members
- /// <summary>
- /// Logs an entry using the Enterprise Library logging.
- /// For logging a Category.Exception type,it is preferred to use
- /// the EnterpriseLibraryLoggerAdapter.Exception methods."
- /// </summary>
- public void Log( string message,Category category,Priority priority )
- {
- if( category == Category.Exception )
- {
- Exception( new Exception( message ),ExceptionPolicies.Default );
- return;
- }
- Logger.Write( message,category.ToString(),( int )priority );
- }
- #endregion
- /// <summary>
- /// Logs an entry using the Enterprise Library Logging.
- /// </summary>
- /// <param name="entry">the LogEntry object used to log the
- /// entry with Enterprise Library.</param>
- public void Log( LogEntry entry )
- {
- Logger.Write( entry );
- }
- // Other methods if needed,i.e.,a default Exception logger.
- public void Exception ( Exception ex ) { // do stuff }
- }
MyCustomLoggerAdapterExtendedAdapter是从MyCustomLoggerAdapter导出的,可以为更加完整的记录器提供其他构造函数.
- public class MyCustomLoggerAdapterExtendedAdapter : MyCustomLoggerAdapter,IFormalLogger
- {
- private readonly ILoggingPolicySection _config;
- private LogEntry _infoPolicy;
- private LogEntry _debugPolicy;
- private LogEntry _warnPolicy;
- private LogEntry _errorPolicy;
- private LogEntry InfoLog
- {
- get
- {
- if( _infoPolicy == null )
- {
- LogEntry log = GetLogEntryByPolicyName( LogPolicies.Info );
- _infoPolicy = log;
- }
- return _infoPolicy;
- }
- }
- // removed backing code for brevity
- private LogEntry DebugLog... WarnLog... ErrorLog
- // ILoggingPolicySection is passed via constructor injection in the bootstrapper
- // and is used to configure varIoUs logging policies.
- public MyCustomLoggerAdapterExtendedAdapter ( ILoggingPolicySection loggingPolicySection )
- {
- _config = loggingPolicySection;
- }
- #region IFormalLogger Members
- /// <summary>
- /// Info: informational statements concerning program state,/// representing program events or behavior tracking.
- /// </summary>
- /// <param name="message"></param>
- public void Info( string message )
- {
- InfoLog.Message = message;
- InfoLog.ExtendedProperties.Clear();
- base.Log( InfoLog );
- }
- /// <summary>
- /// Debug: fine-grained statements concerning program state,/// typically used for debugging.
- /// </summary>
- /// <param name="message"></param>
- public void Debug( string message )
- {
- DebugLog.Message = message;
- DebugLog.ExtendedProperties.Clear();
- base.Log( DebugLog );
- }
- /// <summary>
- /// Warn: statements that describe potentially harmful
- /// events or states in the program.
- /// </summary>
- /// <param name="message"></param>
- public void Warn( string message )
- {
- WarnLog.Message = message;
- WarnLog.ExtendedProperties.Clear();
- base.Log( WarnLog );
- }
- /// <summary>
- /// Error: statements that describe non-fatal errors in the application;
- /// sometimes used for handled exceptions. For more defined Exception
- /// logging,use the Exception method in this class.
- /// </summary>
- /// <param name="message"></param>
- public void Error( string message )
- {
- ErrorLog.Message = message;
- ErrorLog.ExtendedProperties.Clear();
- base.Log( ErrorLog );
- }
- /// <summary>
- /// Logs an Exception using the Default EntLib Exception policy
- /// as defined in the Exceptions.config file.
- /// </summary>
- /// <param name="ex"></param>
- public void Exception( Exception ex )
- {
- base.Exception( ex,ExceptionPolicies.Default );
- }
- #endregion
- /// <summary>
- /// Creates a LogEntry object based on the policy name as
- /// defined in the logging config file.
- /// </summary>
- /// <param name="policyName">name of the policy to get.</param>
- /// <returns>a new LogEntry object.</returns>
- private LogEntry GetLogEntryByPolicyName( string policyName )
- {
- if( !_config.Policies.Contains( policyName ) )
- {
- throw new ArgumentException( string.Format(
- "The policy '{0}' does not exist in the LoggingPoliciesCollection",policyName ) );
- }
- ILoggingPolicyElement policy = _config.Policies[policyName];
- var log = new LogEntry();
- log.Categories.Add( policy.Category );
- log.Title = policy.Title;
- log.EventId = policy.EventId;
- log.Severity = policy.Severity;
- log.Priority = ( int )policy.Priority;
- log.ExtendedProperties.Clear();
- return log;
- }
- }
- public interface IFormalLogger
- {
- void Info( string message );
- void Debug( string message );
- void Warn( string message );
- void Error( string message );
- void Exception( Exception ex );
- }
在Bootstrapper中:
- public class MyProjectBootstrapper : UnityBootstrapper
- {
- protected override void ConfigureContainer()
- {
- // ... arbitrary stuff
- // create constructor injection for the MyCustomLoggerAdapterExtendedAdapter
- var logPolicyConfigSection = ConfigurationManager.GetSection( LogPolicies.CorporateLoggingConfiguration );
- var injectedLogPolicy = new InjectionConstructor( logPolicyConfigSection as LoggingPolicySection );
- // register the MyCustomLoggerAdapterExtendedAdapter
- Container.RegisterType<IFormalLogger,MyCustomLoggerAdapterExtendedAdapter>(
- new ContainerControlledLifetimeManager(),injectedLogPolicy );
- }
- private readonly MyCustomLoggerAdapter _logger = new MyCustomLoggerAdapter();
- protected override ILoggerFacade LoggerFacade
- {
- get
- {
- return _logger;
- }
- }
- }
最后,要使用任何一个记录器,您需要做的就是将适当的接口添加到类的构造函数中,并且UnityContainer将为您注入记录器:
- public partial class Shell : Window,IShellView
- {
- private readonly IFormalLogger _logger;
- private readonly ILoggerFacade _loggerFacade;
- public Shell( IFormalLogger logger,ILoggerFacade loggerFacade )
- {
- _logger = logger;
- _loggerFacade = loggerFacade
- _logger.Debug( "Shell: Instantiating the .ctor." );
- _loggerFacade.Log( "My Message",Category.Debug,Priority.None );
- InitializeComponent();
- }
- #region IShellView Members
- public void ShowView()
- {
- _logger.Debug( "Shell: Showing the Shell (ShowView)." );
- _loggerFacade.Log( "Shell: Showing the Shell (ShowView).",Priority.None );
- this.Show();
- }
- #endregion
- }
我不认为你需要一个单独的模块用于日志策略.通过将日志记录策略添加到基础架构模块,所有其他模块将获得所需的引用(假设您将基础架构模块添加为其他模块的参考).通过将Logger添加到Boostrapper,您可以让UnityContainer根据需要注入日志记录策略.
CodePlex上的CompositeWPF contrib项目还有一个simple example of uisng Log4Net.
HTH的