log4net封装扩展后不能在.NET Framework 4.0下正常运行

简单对log4net做了一下封装,并使用ILMerge进行程序集合并。

解决方案是.NET Framework 4.0,开发环境Win10 .NET Framework 4.8。

4.0的项目生成后在4.0环境下不能正常运行。

1、自定义了一个Layout使用Properties来实现扩展输出日志分类和标题

因使用了 loggingEvent.LookupProperty(key)方法,在.NET Framework 4.0环境下运行异常

.NET Framework 4使用 loggingEvent.Properties[key] 时正常

namespace SharpCode.Utils.Log4net
{
    public class CustomLayout : PatternLayout
    {
        public CustomLayout()
        {
            this.AddConverter("Catalog", typeof(CatalogPatternConverter));
            this.AddConverter("Title", typeof(TitlePatternConverter));
        }
    }

    public class TitlePatternConverter : PatternLayoutConverter
    {
        protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
        {
            //loggingEvent.LookupProperty("Title")
            var title = loggingEvent.Properties["Title"] == null ? "无标题" : loggingEvent.Properties["Title"];
            WriteObject(writer, loggingEvent.Repository, title);
        }
    }

    public class CatalogPatternConverter : PatternLayoutConverter
    {
        //loggingEvent.LookupProperty("Catalog")
        protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
        {
            var catalog = loggingEvent.Properties["Catalog"] == null ? "未分类" : loggingEvent.Properties["Catalog"];
            WriteObject(writer, loggingEvent.Repository, catalog);
        }
    }
}

在过滤器设置过程中存在同样的问题

按Catalog属性来区分存放WIN_UI和WEB_SERVICE日志时,过滤器设置如下

<filter type="log4net.Filter.LevelRangeFilter">
    <LevelMin value="DEBUG"/>
    <LevelMax value="FATAL"/>
    <acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.PropertyFilter">
    <key value="Catalog" />
    <regexToMatch value="^WIN_UI" />
    </filter>
<filter type="log4net.Filter.DenyAllFilter"/>
----------------------------------------------------------
<filter type="log4net.Filter.LevelRangeFilter">
    <LevelMin value="DEBUG"/>
    <LevelMax value="FATAL"/>
    <acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.PropertyFilter">
    <key value="Catalog" />
    <regexToMatch value="^WEB_SERVICE" />
</filter>
<filter type="log4net.Filter.DenyAllFilter"/>

log4net.Filter.PropertyFilter 在.NET Framework 4.0下不工作

查看log4net.Filter.PropertyFilter的源代码部分

public override FilterDecision Decide(LoggingEvent loggingEvent)
{
    if (loggingEvent == null)
    {
        throw new ArgumentNullException("loggingEvent");
    }
    if (m_key == null)
    {
        return FilterDecision.Neutral;
    }
    object obj = loggingEvent.LookupProperty(m_key);
    string text = loggingEvent.Repository.RendererMap.FindAndRender(obj);
    if (text == null || (m_stringToMatch == null && m_regexToMatch == null))
    {
        return FilterDecision.Neutral;
    }
    if (m_regexToMatch != null)
    {
        if (!m_regexToMatch.Match(text).Success)
        {
            return FilterDecision.Neutral;
        }
        if (m_acceptOnMatch)
        {
            return FilterDecision.Accept;
        }
        return FilterDecision.Deny;
    }
    if (m_stringToMatch != null)
    {
        if (text.IndexOf(m_stringToMatch) == -1)
        {
            return FilterDecision.Neutral;
        }
        if (m_acceptOnMatch)
        {
            return FilterDecision.Accept;
        }
        return FilterDecision.Deny;
    }
    return FilterDecision.Neutral;
}

标红的部分不工作,可以按源代码自己写一个PropertyFilter替换掉其中的loggingEvent.LookupProperty(m_key)为loggingEvent.Properties[m_key]

再给过滤器中的类型改为自己写的PropertyFilter

针对loggingEvent.LookupProperty()方法的问题,可以自行下载源码重新用net4+2005编译生成一个纯4.0的版本。

 

2、4.0项目中nuget的ILMerge 3.0.29包能装上,是net452的。

应该使用2.14.1208版本的包中的ILMerge.exe做为合并工具

可以用反编译工具查看程序集的TargetFramework,确认使用正确的版本

如 [assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]

应当在最高只有.NET Framework 4的环境下合并程序集,生成的文件才能在.NET Framework 4.0下运行,否则mscorlib会报引用异常。

posted @ 2020-03-31 21:48  yusufeng  阅读(347)  评论(0编辑  收藏  举报