本節主要介紹解決方案中的Microsoft.Framework.Logging.Abstractions、Microsoft.Framework.Logging倆個工程。
這倆個工程中所有類的關系如下圖所示:

首先我們可以發現處于核心的是中間的四個接口:ILogger、ILoggerFactory、ILoggerPRovider、ILogValues。
接口的定義源碼如下:

public interface ILogger { void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter); bool IsEnabled(LogLevel logLevel); IDisposable BeginScopeImpl(object state); }ILogger
public interface ILoggerFactory { LogLevel MinimumLevel { get; set; } ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider); }ILoggerFactory
public interface ILoggerProvider { ILogger CreateLogger(string name); }ILoggerProvider
public interface ILogValues { IEnumerable<KeyValuePair<string, object>> GetValues(); }ILogValuesILogger以及實現類
ILogger接口、ILogger<TCategoryName>(沒有任何定義)、Logger<T>這種泛型繼承是否有相識之感,之前的博客文章中已經對于這種情況有所介紹([Asp.net 5] Localization-resx資源文件的管理中IStringLocalizer 、IStringLocalizer<T> 、StringLocalizer<TResourceSource>是一致的)。實際Logger<T>中T是ILogger的實例子類,實際就是使用代理模式,內部包含ILogger實例,并且所有對外的方法都僅僅是內部ILogger實例的封裝。

public class Logger<T> : ILogger<T> { private readonly ILogger _logger; /// <summary> /// Creates a new <see cref="Logger{T}"/>. /// </summary> /// <param name="factory">The factory.</param> public Logger(ILoggerFactory factory) { _logger = factory.CreateLogger<T>(); } IDisposable ILogger.BeginScopeImpl(object state) { return _logger.BeginScopeImpl(state); } bool ILogger.IsEnabled(LogLevel logLevel) { return _logger.IsEnabled(logLevel); } void ILogger.Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter) { _logger.Log(logLevel, eventId, state, exception, formatter); } } LoggerLogger類同樣實現了ILogger接口,也同樣使用了代理模式,不過不同于Logger<T>泛型,Logger類有自己的內部邏輯。而是在內部封裝了ILogger[] _loggers對象。使得Logger更像LoggerManage。但是由于Logger同樣實現Logger接口,所以Logger類是管理其它Logger類的代理。而Logger內部的_loggers是通過LoggerFactory對象封裝的。當記錄日志時,依次遍歷內部的_loggers對象,進行寫日志操作。

internal class Logger : ILogger { private readonly LoggerFactory _loggerFactory; private readonly string _name; private ILogger[] _loggers = new ILogger[0]; public Logger(LoggerFactory loggerFactory, string name) { _loggerFactory = loggerFactory; _name = name; var providers = loggerFactory.GetProviders(); _loggers = new ILogger[providers.Length]; for (var index = 0; index != providers.Length; index++) { _loggers[index] = providers[index].CreateLogger(name); } } public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter) { if (logLevel >= _loggerFactory.MinimumLevel) { foreach (var logger in _loggers) { logger.Log(logLevel, eventId, state, exception, formatter); } } } public bool IsEnabled(LogLevel logLevel) { if (logLevel < _loggerFactory.MinimumLevel) { return false; } foreach (var logger in _loggers) { if (logger.IsEnabled(logLevel)) { return true; } } return false; } public IDisposable BeginScopeImpl(object state) { var loggers = _loggers; var scope = new Scope(loggers.Length); for (var index = 0; index != loggers.Length; index++) { scope.SetDisposable(index, loggers[index].BeginScopeImpl(state)); } return scope; } internal void AddProvider(ILoggerProvider provider) { var logger = provider.CreateLogger(_name); _loggers = _loggers.Concat(new[] { logger }).ToArray(); } private class Scope : IDisposable { private bool _isDisposed; private IDisposable _disposable0; private IDisposable _disposable1; private readonly IDisposable[] _disposable; public Scope(int count) { if (count > 2) { _disposable = new IDisposable[count - 2]; } } public void SetDisposable(int index, IDisposable disposable) { if (index == 0) { _disposable0 = disposable; } else if (index == 1) { _disposable1 = disposable; } else { _disposable[index - 2] = disposable; } } protected virtual void Dispose(bool disposing) {
新聞熱點
疑難解答