基于AOP+Log4Net+AutoFac日志框架

1.项目概述

这是一个基于 C# 的 WPF 项目 WpfApp12log4net,它综合运用了依赖注入、日志记录和接口实现等多种技术,同时使用了 AutofacCastle.Corelog4net 等第三方库。

2.配置log4net

新建一个Log4Net.config,配置需要记录的日志信息,主要该文件在编译后要生成到debug或者release文件夹下。

配置文件如下:

复制代码
<?xml version="1.0" encoding="utf-8"?>
    <log4net>
    <!--错误日志类-->
    <logger name="logerror">
      <!--日志类的名字-->
      <level value="ALL" />
      <!--定义记录的日志级别-->
      <appender-ref ref="ErrorAppender" />
      <!--记录到哪个介质中去-->
    </logger>
    <!--信息日志类-->
    <logger name="loginfo">
      <level value="ALL" />
      <appender-ref ref="InfoAppender" />
    </logger>

	<!--MES日志类-->
	<logger name="Mesinfo">
	  <level value="ALL" />
	  <appender-ref ref="MesAppender" />
	</logger>


		<!--错误日志附加介质-->
    <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
      <!-- name属性指定其名称,type则是log4net.Appender命名空间的一个类的名称,意思是,指定使用哪种介质-->
      <param name="File" value="Log\\LogError2\\" />
      <!--日志输出到exe程序这个相对目录下-->
      <param name="AppendToFile" value="true" />
      <!--输出的日志不会覆盖以前的信息-->
      <param name="MaxSizeRollBackups" value="100" />
      <!--备份文件的个数-->
      <param name="MaxFileSize" value="1024" />
      <!--当个日志文件的最大大小-->
      <param name="StaticLogFileName" value="false" />
      <!--是否使用静态文件名-->
      <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
      <!--日志文件名-->
      <param name="RollingStyle" value="Date" />
      <!--文件创建的方式,这里是以Date方式创建-->
      <!--错误日志布局-->
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%n异常时间:%d [%t]  %n异常级别:%-5p  %n异 常 类:%c [%x]  %n%m  %n "  />
      </layout>
    </appender>
 
		
		<!--信息日志附加介质-->
    <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Log\\LogInfo\\"/>
      <param name="AppendToFile" value="true"/>
      <param name="MaxFileSize" value="10240"/>
      <param name="MaxSizeRollBackups" value="100" />
      <param name="StaticLogFileName" value="false" />  
      <param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
      <param name="RollingStyle" value="Date" />
      <!--信息日志布局-->
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="[时间] %d [%t] [信息] %m%n"  />
      </layout>
    </appender>


		<!--信息日志附加介质-->
		<appender name="MesAppender" type="log4net.Appender.RollingFileAppender">
			<param name="File" value="Log\\MesInfo\\"/>
			<param name="AppendToFile" value="true"/>
			<param name="MaxFileSize" value="10240"/>
			<param name="MaxSizeRollBackups" value="100" />
			<param name="StaticLogFileName" value="false" />
			<param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
			<param name="RollingStyle" value="Date" />
			<!--信息日志布局-->
			<layout type="log4net.Layout.PatternLayout">
				<param name="ConversionPattern" value="[时间] %d [%t] [信息] %m%n"  />
			</layout>
		</appender>
		
  </log4net>

3.加载配置文件

要在代码启动的时候加载,以下是涉及到其他配置,所以是动态路径的案例。

复制代码
  string configFilePath = "Log4Net.config";
  var fileInfo = new FileInfo(configFilePath);
  if (!fileInfo.Exists)
  {
      throw new FileNotFoundException($"配置文件 {configFilePath} 不存在!");
  }
  XmlConfigurator.Configure(fileInfo);

  string path = @"C:\\Log4NetTestFile\\";
  string[] fileName = { "InfoAppender", "ErrorAppender", "MesAppender" };
  ILoggerRepository repository = LogManager.GetRepository(Assembly.GetEntryAssembly());
  for (int i = 0; i < fileName.Length; i++)
  {
      log4net.Appender.RollingFileAppender appender = repository.GetAppenders().OfType<log4net.Appender.RollingFileAppender>().FirstOrDefault(a => a.Name == fileName[i]);
      if (appender != null)
      {
          appender.File = path + fileName[i] + "\\";
          appender.ActivateOptions();
      }
  }

4.搭建日志方法类LogHelp

日志存储的方法写在里面。

复制代码
using log4net;
using log4net.Config;
using System;
using System.IO;

namespace WpfApp12log4net
{
    public class LogHelp
    {
        private  readonly ILog log_info = LogManager.GetLogger("loginfo");
        private  readonly ILog log_error = LogManager.GetLogger("logerror");
        private  readonly ILog mes_info = LogManager.GetLogger("Mesinfo");

        public  void Info(string info)
        {
            if (log_info.IsInfoEnabled)
            {
                log_info.Info(info);
            }
        }

        public  void mesinfo(string info)
        {
            if (mes_info.IsInfoEnabled)
            {
                mes_info.Info(info);
            }
        }

        public  void Error(string error, Exception ex)
        {
            if (log_error.IsErrorEnabled)
            {
                log_error.Error(error, ex);
            }
        }

        public  void Error(string error)
        {
            if (log_error.IsErrorEnabled)
            {
                log_error.Error(error);
            }
        }
    }
}

4.拦截器搭建LoggingInterceptor

复制代码
using Castle.DynamicProxy;
using log4net;
using System;
using System.Reflection;

namespace WpfApp12log4net
{
    public class LoggingInterceptor : IInterceptor
    {

        private readonly LogHelp logHelp;

        public LoggingInterceptor(LogHelp logHelp)
        {
            this.logHelp = logHelp;
        }

        public void Intercept(IInvocation invocation)
        {
            try
            {
                logHelp.Info($"开始执行方法: {invocation.Method.Name}");
                logHelp.Info($"参数: {string.Join(", ", invocation.Arguments)}");

                // 执行方法并获取返回值
                invocation.Proceed();
                object result = invocation.ReturnValue;

                // 记录返回值(如果方法不是 void)s
                if (invocation.Method.ReturnType != typeof(void))
                {
                    logHelp.Info($"方法 {invocation.Method.Name} 返回值: {result ?? "null"}");
                }

                logHelp.Info($"方法 {invocation.Method.Name} 执行完毕");
            }
            catch (Exception ex)
            {
                // 记录完整的异常信息(包括堆栈跟踪)
                logHelp.Error($"方法 {invocation.Method.Name} 执行出错: {ex.ToString()}", ex);
                throw; // 重新抛出异常,确保调用方能够捕获
            }
        }
    }
}

5.创建服务类

复制代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace WpfApp12log4net
    {
        public class Service : IService
        {

            public string methodservice11(string ttt)
            {
                try
                {
                    string[] str = null;
                    if (str[1] == "1")
                    {
                        // 此部分代码会触发异常
                    }
                    else
                    {
                        // 此部分代码会触发异常
                    }
                }
                catch (Exception ex)
                {
                    //LogHelp.Error(ex.Message);
                    //LogHelp.Error("异常", ex);
                }
                return "这是参数返回........的内容";
            }


            public string methodservice12(string ttt)
            {
                try
                {
                    //string[] str = null;
                    //if (str[1] == "1")
                    //{
                    //    // 此部分代码会触发异常
                    //}
                    //else
                    //{
                    //    // 此部分代码会触发异常
                    //}
                }
                catch (Exception ex)
                {
                    //LogHelp.Error(ex.Message);
                    //LogHelp.Error("异常", ex);
                }
                return "这是参数返回........的内容";
            }
        }
    }









using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApp12log4net
{
    public class Service2 : IService2
    {

        public string methodservice21(string ttt)
        {
            try
            {
                string[] str = null;
                if (str[1] == "1")
                {
                    // 此部分代码会触发异常
                }
                else
                {
                    // 此部分代码会触发异常
                }
            }
            catch (Exception ex)
            {
                //LogHelp.Error(ex.Message);
                //LogHelp.Error("异常", ex);
            }
            return "这是参数返回........的内容";
        }
    }
}

6.创建服务接口

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApp12log4net
{
    public interface IService
    {
     
        string methodservice11(string ttt);


        string methodservice12(string ttt);

    }
}






using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApp12log4net
{
    public interface IService2
    {
   
        string methodservice21(string ttt);
    }
}

7.依赖注入

复制代码
          var builder = new ContainerBuilder();
          var proxyGenerator = new ProxyGenerator();

          // 先注册 LogHelp
          builder.RegisterType<LogHelp>().AsSelf();
          // 注册 LoggingInterceptor
          builder.RegisterType<LoggingInterceptor>().AsSelf();

          // 注册 IService 接口及其实现类 Service
          builder.Register(c =>
          {
              var service = new Service();
              var interceptor = c.Resolve<LoggingInterceptor>();
              return proxyGenerator.CreateInterfaceProxyWithTarget(typeof(IService), service, interceptor) as IService;
          }).As<IService>();

          // 注册 IService2 接口及其实现类 Service2
          builder.Register(c =>
          {
              var service = new Service2();
              var interceptor = c.Resolve<LoggingInterceptor>();
              return proxyGenerator.CreateInterfaceProxyWithTarget(typeof(IService2), service, interceptor) as IService2;
          }).As<IService2>();

          // 注册 MainWindow
          builder.RegisterType<MainWindow>().AsSelf();

          Container = builder.Build();

8.总结

1. 依赖注入(Dependency Injection,DI)

使用 Autofac 库实现依赖注入。通过 ContainerBuilder 构建容器,注册接口及其实现类(如 IServiceServiceIService2Service2 )以及窗口类(MainWindow )等,在程序运行时由容器负责创建对象并注入依赖关系,降低组件间耦合度。

2. 动态代理(Dynamic Proxy)

借助 Castle.DynamicProxy 库实现动态代理。定义了 LoggingInterceptor 类实现 IInterceptor 接口,在方法执行前后进行日志记录等操作。在注册服务时,利用 ProxyGenerator 创建代理对象,将拦截器应用到目标服务(ServiceService2 )上,实现对服务方法调用的拦截和增强 。

3. 日志记录

运用 log4net 日志框架进行日志记录。通过配置文件(log4net.config )设置不同类型日志(错误日志、信息日志、MES 日志 )的记录方式,包括日志级别、日志存储路径、文件滚动策略、日志格式等。在代码中通过 LogHelp 类封装的方法,在不同业务场景(方法执行、异常处理等 )下记录日志。

4. WPF(Windows Presentation Foundation)

这是一个 WPF 项目,使用 WPF 技术构建桌面应用程序界面。定义了 MainWindow 类继承自 Window,实现窗口相关功能,如按钮点击事件处理等,利用 WPF 的特性来呈现用户界面和交互逻辑。

相关推荐
廿一夏5 小时前
MySql存储引擎与索引
数据库·sql·mysql
Mahir085 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
商业模式源码开发5 小时前
实体门店低获客成本增长案例:3 人转介绍模型 + 消费返还机制落地分析
大数据·商业模式·私域流量
RyFit6 小时前
SpringAI 常见问题及解决方案大全
java·ai
石山代码6 小时前
C++ 内存分区 堆区
java·开发语言·c++
元拓数智7 小时前
智能分析落地卡壳?先补好「数据关系+语义治理」这层技术基建
大数据·分布式·ai·spark·数据关系·语义治理
绝知此事7 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
无风听海7 小时前
C# 隐式转换深度解析
java·开发语言·c#
lzhdim7 小时前
SQL 入门 15:SQL 事务:从 ACID 到四种常见的并发问题
数据库·sql
瀚高PG实验室7 小时前
瀚高企业版V9.1.1在pg_restore还原备份文件时提示extract函数语法问题
数据库·瀚高数据库