在Prism中最简单的记录日志的方式是覆盖Bootstrapper
中的LoggerFacade
属性。通过覆盖LoggerFacade
,只要Logger实现了ILoggerFacade
接口,就可以传入任何需要的Logger实例和配置信息。
我发现以下方法在记录日志方面效果很好(我使用的是Enterprise Libary Logging块,但应用于Log4Net应该也很容易):
在你的Shell中创建一个Bootstrapper:
-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
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
public void Log( LogEntry entry )
{
Logger.Write( entry );
}
public void Exception ( Exception ex ) {
}
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;
}
}
private LogEntry DebugLog... WarnLog... ErrorLog
public MyCustomLoggerAdapterExtendedAdapter ( ILoggingPolicySection loggingPolicySection )
{
_config = loggingPolicySection;
}
#region IFormalLogger Members
public void Info( string message )
{
InfoLog.Message = message;
InfoLog.ExtendedProperties.Clear();
base.Log( InfoLog );
}
public void Debug( string message )
{
DebugLog.Message = message;
DebugLog.ExtendedProperties.Clear();
base.Log( DebugLog );
}
public void Warn( string message )
{
WarnLog.Message = message;
WarnLog.ExtendedProperties.Clear();
base.Log( WarnLog );
}
public void Error( string message )
{
ErrorLog.Message = message;
ErrorLog.ExtendedProperties.Clear();
base.Log( ErrorLog );
}
public void Exception( Exception ex )
{
base.Exception( ex, ExceptionPolicies.Default );
}
#endregion
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()
{
var logPolicyConfigSection = ConfigurationManager.GetSection( LogPolicies.CorporateLoggingConfiguration );
var injectedLogPolicy = new InjectionConstructor( logPolicyConfigSection as LoggingPolicySection );
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).", Category.Debug, Priority.None );
this.Show();
}
#endregion
}
我认为您不需要单独的日志记录模块。通过将日志记录策略添加到基础架构模块中,所有其他模块都将获得所需的引用(假设您将基础架构模块添加为其他模块的引用)。并且通过在Boostrapper中添加记录器,您可以让UnityContainer根据需要注入日志记录策略。
在CodePlex的CompositeWPF contrib项目上,还有一个使用Log4Net的简单示例(链接)。
希望对你有所帮助。