基于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 的特性来呈现用户界面和交互逻辑。

相关推荐
倔强的石头1062 小时前
【金仓数据库】ksql 指南(一) 连接本地 KingbaseES 数据库与基础交互
数据库·oracle·kingbasees·金仓数据库·ksql
代码萌新知4 小时前
设计模式学习(五)装饰者模式、桥接模式、外观模式
java·学习·设计模式·桥接模式·装饰器模式·外观模式
数据小子2145 小时前
【自记】MaxCompute中的冒烟测试
大数据·maxcompute
iナナ7 小时前
Spring Web MVC入门
java·前端·网络·后端·spring·mvc
未来之窗软件服务7 小时前
万象EXCEL开发(九)excel 高级混合查询 ——东方仙盟金丹期
大数据·excel·仙盟创梦ide·东方仙盟·万象excel
驱动探索者7 小时前
find 命令使用介绍
java·linux·运维·服务器·前端·学习·microsoft
卷Java7 小时前
违规通知功能修改说明
java·数据库·微信小程序·uni-app
CoderYanger7 小时前
优选算法-双指针:2.复写零
java·后端·算法·leetcode·职场和发展
小雨凉如水7 小时前
k8s学习-pod的生命周期
java·学习·kubernetes
李宥小哥7 小时前
C#基础10-结构体和枚举
java·开发语言·c#