一、日志模块类图

1、ILogger接口及实现

2、ILoggerFactory接口及实现
3、其他

二、NullLogger类型
    NullLogger类型是实现ILogger接口的空类型。它的 IsEnabled 方法总是返回false;Log 方法是个空实现。在代码中要用到日志的地方设计1个 NullLogger属性 作为占位符,在代码运行时将这个对象替换为真正的日志对象。如果不替换,则代码也能编译成功,运行时也不会出错。

 publicclassNullLogger:ILogger
{
privatestaticreadonlyILogger _instance =newNullLogger();
publicstaticILoggerInstance
{
get
{
return _instance;
}
}
#region ILogger 成员 public bool IsEnabled(LogLevel level)
{
returnfalse;
} publicvoidLog(LogLevel level,Exception exception,string format,paramsobject[] args)
{ } #endregion
}
三、和autofac的结合使用
    在orchard中,autofac的使用无处不在。日志模块也不例外。前面说过,NullLogger 类型相当于1个日志类型的占位符,在运行时可以被替换为真实的日志类型。那在运行时如何替换呢?这就要和autofac结合在一起使用
1、LoggingModule类
    LoggingModule类继承了Module类型。Module类型是autofac的类型。

 publicclassLoggingModule:Module
{
privatereadonlyConcurrentDictionary<string,ILogger> _loggerCache; publicLoggingModule()
{
_loggerCache =newConcurrentDictionary<string,ILogger>();
} protectedoverridevoidLoad(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().WithParameter(newNamedParameter("isFullTrust",false)); // call CreateLogger in response to the request for an ILogger implementation
moduleBuilder.Register(CreateLogger).As<ILogger>().InstancePerDependency();
} protectedoverridevoidAttachToComponentRegistration(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);
};
} privateIEnumerable<Action<IComponentContext,object>>BuildLoggerInjectors(Type componentType)
{
// 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()==)// must not be an indexer
.Where(x => x.Accessors.Length!=|| x.Accessors[].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();
if(component != instance.GetType().ToString())
{
return;
}
var logger = _loggerCache.GetOrAdd(component, key => ctx.Resolve<ILogger>(newTypedParameter(typeof(Type), componentType)));
propertyInfo.SetValue(instance, logger,null);
};
}
} privatestaticILoggerCreateLogger(IComponentContext context,IEnumerable<Parameter> parameters)
{
// return an ILogger in response to Resolve<ILogger>(componentTypeParameter)
var loggerFactory = context.Resolve<ILoggerFactory>();
var containingType = parameters.TypedAs<Type>();
return loggerFactory.CreateLogger(containingType);
}
}
    
1)   Load方法在 builder.Build()时会被调用,这里注册了 3个类型
moduleBuilder.RegisterType<CastleLoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
 
moduleBuilder.RegisterType<OrchardLog4netFactory>().As<Castle.Core.Logging.ILoggerFactory>().InstancePerLifetimeScope().WithParameter(new NamedParameter("isFullTrust", false));
      
moduleBuilder.Register(CreateLogger).As<ILogger>().InstancePerDependency();
 
2) AttachToComponentRegistration方法也会在 builder.Build()时会被调用,它会调用BuildLoggerInjectors 方法。而 BuildLoggerInjectors方法会检查 类型 中的属性,如果属性是 ILogger接口,则会被替换为 CastleLogger或 OrchardLog4netLogger类。当然你也能注册为自定义的其他日志类型。
 
四、log4net 设置
    orchard使用log4net作为日志的具体实现。配置如下

 <?xml version="1.0" encoding="utf-8"?>
<log4net>
<root> <priority value="ERROR"/>
<appender-refref="error-file"/>
</root> <logger name="NHibernate.Cache">
<priority value="ERROR"/>
</logger> <logger name="NHibernate.AdoNet.AbstractBatcher">
<priority value="ERROR"/>
</logger> <logger name="NHibernate.Util.ADOExceptionReporter">
<priority value="ERROR"/>
</logger> <appender name="error-file" type="Orchard.Logging.OrchardFileAppender">
<file value="orchard-error"/>
<appendToFile value="true"/>
<immediateFlush value="false"/>
<staticLogFileName value="false"/>
<rollingStyle value="Date"/>
<datepattern value="-yyyy.MM.dd'.log'"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %logger - %P{Tenant} - %message%newline %P{Url}%newline"/>
</layout>
</appender>
</log4net>
 
 
五、orchard日志模块使用示例
1、要使用日志的类型
  1.  /// <summary>
    /// 要使用日志的类型
    /// </summary>
    publicclassThing
    {
    publicThing()
    {
    Logger=NullLogger.Instance;
    }
    /// <summary>
    /// 设置类型为 ILogger 的属性
    /// </summary>
    publicILoggerLogger
    {
    get;
    set;
    }
    publicvoidTestMethod()
    {
    //这使用Log方法则 Logger属性 会被设置为 CastleLogger类;使用Error方法 Logger属性 会被设置为OrchardLog4netLogger类
    Logger.Log(Orchard.Logging.LogLevel.Error,newException("测试异常"),"测试异常使用CastleLogger类型");
    Logger.Error(newException("测试异常"),"测试异常使用OrchardLog4netLogger类型");
    }
    }
2、调用
  1.  publicvoidCreateTest()
    {
    var builder =newContainerBuilder();//构建autofac容器
    builder.RegisterModule(newLoggingModule());//注册LoggingModule
    builder.RegisterType<Thing>();//注册 Thing类型
    var container = builder.Build();//Build 容器
    var thing = container.Resolve<Thing>();//从容器中解析 Thing类型
    thing.TestMethod();//调用TestMethod方法,则会调用日志
    }
 
 
    
 
 

 

Orchard学习 01、orchard日志的更多相关文章

  1. Orchard 学习-安装Orchard

    前段时间使用一个ABP的框架进行了一个简单CMS开发.但感觉自己开发CMS不够灵活和通用,所以还是学习一下Orchard.学习的第一步,阅读官方的文档.由于是英文,所以我对其进行了翻译和记录,方便自己 ...

  2. 200. Orchard学习 目录

    201. Orchard学习 一.基础 210. Orchard学习 二.启动 211. Orchard学习 二 1.Application_Start 212. Orchard学习 二 2.Manu ...

  3. Orchard学习笔记

    1.下载Orchard sourcrs资源文件,同时也可以去百度下载中文包 资源地址(https://github.com/OrchardCMS/Orchard/releases/download/1 ...

  4. Orchard学习系列-----如何运行的

    感慨:当接触到微软这套程序时,代码实在是太好了,好的几乎都读不懂.很久之前就对这个套开源程序特别感兴趣,但读不明白也让人郁闷. 背景(Orchard官网): 可组装系统的CMS系统,OrChard在运 ...

  5. ThinkPhp学习01

    原文:ThinkPhp学习01 一.ThinkPHP的介绍           MVC  M - Model 模型                工作:负责数据的操作  V - View  视图(模板 ...

  6. spring学习(01)之IOC

    spring学习(01)之IOC IOC:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创 ...

  7. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  8. Java虚拟机JVM学习01 流程概述

    Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...

  9. Android Testing学习01 介绍 测试测什么 测试的类型

    Android Testing学习01 介绍 测试测什么 测试的类型 Android 测试 测什么 1.Activity的生命周期事件 应该测试Activity的生命周期事件处理. 如果你的Activ ...

随机推荐

  1. Day23-Model操作,Form操作和序列化操作

    参考源出处:http://blog.csdn.net/fgf00/article/details/54629502 1. 搭建环境请参考:http://www.cnblogs.com/momo8238 ...

  2. BZOJ 3195 [Jxoi2012]奇怪的道路 | 状压DP

    传送门 BZOJ 3195 题解 这是一道画风正常的状压DP题. 可以想到,\(dp[i][j][k]\)表示到第\(i\)个点.已经连了\(j\)条边,当前\([i - K, i]\)区间内的点的度 ...

  3. Mountainous landscape

    Description 现在在平面上给你一条折线 \(P_1P_2 \cdots P_n\) . \(x\) 坐标是严格单调递增的.对于每一段折线 \(P_iP_{i+1}\) ,请你找一个最小的 \ ...

  4. 洛谷 P5108 仰望半月的夜空 解题报告

    P5108 仰望半月的夜空 题目描述 半月的夜空中,寄托了多少人与人之间的思念啊 曦月知道,这些思念会汇集成一个字符串\(S(n = |S|)\) 由于思念汇集的过于复杂,因此曦月希望提炼出所有的思念 ...

  5. 解题:HNOI 2015 开店

    题面 根据树上距离的计算方法,可以先把答案化成$\sum dep_i+n*dep_u-\sum 2*dep[LCA(i,u)]$的形式,然后维护$\sum 2*dep[LCA(i,u)]$ 把妖怪们按 ...

  6. nginx代理服务器3--高可用(keepalived)

    keepalived即健康检查,不停的发送心跳包检查nginx是否活着.Nginx至少两台,一主一备.

  7. 本日吐槽!“人傻钱多”的P2P公司是否是程序员的合适选择(群聊天记录的娱乐)

    这个题目“P2P的职位是否是程序员的合适选择”这个问题本身是没啥可以吐槽的 但是每当我们讨论那种类型的公司工资愿意给前端工程师开的最高的时候,P2P这个行业被第一个提出了 目前我收到过面试的企业类型千 ...

  8. Javascript Jquery 中的数组定义与操作

    1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多维数组,但是因为数组里面可以包含对象(数组也是一个对象),所以数组可以通过相互嵌套实现类似多维数 ...

  9. linux - JDK 环境

    JDK安装 vi /etc/profile # 添加环境变量 export JAVA_HOME=/usr/local/jdk1.8.2_45 export CLASSPATH=.:$JAVA_HOME ...

  10. Python实现网页截图(PyQT5)

    方案说明 功能要求:实现网页加载后将页面截取成长图片涉及模块:PyQT5 PIL逻辑说明: 1:完成窗口设置,利用PyQT5 QWebEngineView加载网页地址,待网页加载完成后,调用check ...