Самый простой подход для входа в Prism - переопределить свойство LoggerFacade
в вашем Bootstrapper . Переопределив LoggerFacade
, вы можете передать экземпляр любого Logger, который вам нужен, с любой необходимой конфигурацией, если регистратор реализует интерфейс ILoggerFacade
.
Я нашел следующее, чтобы работать хорошо для ведения журнала (я использую блок ведения журнала Enterprise Libary, но применение чего-то похожего для Log4Net должно быть прямым):
Создайте 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 будет использоваться для переопределения свойства 'LoggerFacade' в Bootstrapper. Он должен иметь конструктор по умолчанию, который сообщает обо всем.
Примечание: переопределяя свойство LoggerFacade
в Bootstrapper, вы предоставляете механизм регистрации, который 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).", Category.Debug, Priority.None );
this.Show();
}
#endregion
}
Не думаю, что вам нужен отдельный модуль для политики ведения журнала. При добавлении политик ведения журнала в ваш модуль инфраструктуры все остальные модули получат необходимые ссылки (при условии, что вы добавите модуль инфраструктуры в качестве ссылки на ваши другие модули). А добавив регистратор в Boostrapper, вы можете позволить UnityContainer внедрять политику журналирования по мере необходимости.
Существует простой пример использования Log4Net в проекте CompositeWPF contrib для CodePlex.
НТН в