• (6)Orchard 开发之 Logging and NullLogger


    NullLogger 很像 NullLocalizer 其实它们都没有干什么实际的工作,orchard 通常会在构造函数中给 ILogger 赋一个 NullLogger.Instance

    Logger = NullLogger.Instance;    这样一看很多人还以为是 NullLogger 打的 log ,其实不是这样的, 你删掉 Logger = NullLogger.Instance;  这条语句也没什么影响,log 一样能打出来。 我暂时还不知道 NullLogger 究竟有什么用。

    相关的类都在 Orchard.Framework\Logging 下:

    首先还是看 LoggingModule 类:

    protected override void Load(ContainerBuilder moduleBuilder) {
                // by default, use Orchard's logger that delegates to Castle's logger factory
                moduleBuilder.RegisterType<CastleLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope(); // 注册工厂方法
                moduleBuilder.RegisterType<OrchardLog4netFactory>().As<Castle.Core.Logging.ILoggerFactory>().InstancePerLifetimeScope(); // 注册工厂方法
    
                // call CreateLogger in response to the request for an ILogger implementation
                moduleBuilder.Register(CreateLogger).As<ILogger>().InstancePerDependency();    // 当需要一个 ILogger 实例时 调 CreateLogger 方法
            }
    
            protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
                var implementationType = registration.Activator.LimitType;
    
                // build an array of actions on this type to assign loggers to member properties
                var injectors = BuildLoggerInjectors(implementationType).ToArray();
    
                // if there are no logger properties, there's no reason to hook the activated event
                if (!injectors.Any())
                    return;
    
                // otherwise, whan an instance of this component is activated, inject the loggers on the instance
                registration.Activated += (s, e) => {
                    foreach (var injector in injectors)
                        injector(e.Context, e.Instance);  
                };
            }
    
            private IEnumerable<Action<IComponentContext, object>> BuildLoggerInjectors(Type componentType) {  // 查找是否定义了 ILogger 属性
                // Look for settable properties of type "ILogger" 
                var loggerProperties = componentType
                    .GetProperties(BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance)
                    .Select(p => new {
                        PropertyInfo = p,
                        p.PropertyType,
                        IndexParameters = p.GetIndexParameters(),
                        Accessors = p.GetAccessors(false)
                    })
                    .Where(x => x.PropertyType == typeof(ILogger)) // must be a logger
                    .Where(x => x.IndexParameters.Count() == 0) // must not be an indexer
                    .Where(x => x.Accessors.Length != 1 || x.Accessors[0].ReturnType == typeof(void)); //must have get/set, or only set
    
                // Return an array of actions that resolve a logger and assign the property
                foreach (var entry in loggerProperties) {
                    var propertyInfo = entry.PropertyInfo;
    
                    yield return (ctx, instance) => {
                        string component = componentType.ToString();
                        var logger = _loggerCache.GetOrAdd(component, key => ctx.Resolve<ILogger>(new TypedParameter(typeof(Type), componentType)));
                        propertyInfo.SetValue(instance, logger, null); // 为 ILogger 赋值
                    };
                }
            }
    
            private static ILogger CreateLogger(IComponentContext context, IEnumerable<Parameter> parameters) {
                // return an ILogger in response to Resolve<ILogger>(componentTypeParameter)
                var loggerFactory = context.Resolve<ILoggerFactory>();   // 注入一个工厂方法 ,这里注入的是 CastleLoggerFactory 在 Load 方法中配置的
                var containingType = parameters.TypedAs<Type>();
                return loggerFactory.CreateLogger(containingType);  // 返回一个 ILogger 对象,这里返回的是 CastleLogger
            }

    所以  ILogger 实际指向的是一个  CastleLogger 对象

    CastleLogger 类中 有一个字段  _castleLogger

    private readonly Castle.Core.Logging.ILogger _castleLogger;

    由上可知这个字段实际会指向   OrchardLog4netLogger 对象

    所以最后真正打 Log 的还是  OrchardLog4netLogger  。

    public interface ILogger {
            bool IsEnabled(LogLevel level);
            void Log(LogLevel level, Exception exception, string format, params object[] args);
        }

    ILogger 只有一个  Log 方法, 但你却可以调 Logger.Debug 等方法,这是因为在  LoggingExtensions  定义了 ILogger 扩展方法。

    Log4net 的配置文件在 Orchard.Web\Config\log4net.config

    默认的 log 会打到 \Orchard.Web\App_Data\Logs 下面

  • 相关阅读:
    错误 2 error C2059: 语法错误:“::”
    完全卸载session 所需要的函数
    header("Location:http://www.baidu.com");
    php str_pad() 用法
    php str_pad();
    设计模式系列-01-开篇
    博客园样式的设置系列-01-侧边栏和皮肤的设置
    vs20132015UML系列之-类图
    php获取当前时间和转换格式
    saltstack:multi-master configuration
  • 原文地址:https://www.cnblogs.com/lesliefang/p/2862008.html
Copyright © 2020-2023  润新知