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

相关推荐
挽风82112 分钟前
Bad Request 400
java·spring
luoluoal21 分钟前
Java项目之基于ssm的QQ村旅游网站的设计(源码+文档)
java·mysql·mybatis·ssm·源码
luoluoal28 分钟前
Java项目之基于ssm的学校小卖部收银系统(源码+文档)
java·mysql·毕业设计·ssm·源码
言小乔.1 小时前
202526 | 消息队列MQ
java·消息队列·消息中间件
懒懒小徐1 小时前
消息中间件面试题
java·开发语言·面试·消息队列
veminhe1 小时前
Node.js 数据库 CRUD 项目示例
数据库·node.js
HX科技1 小时前
树莓派_利用Ubuntu搭建gitlab
数据库·ubuntu·gitlab
pursue.dreams1 小时前
Windows 下 MongoDB ZIP 版本安装指南
数据库·windows·mongodb
转转技术团队2 小时前
加Log就卡?不加Log就瞎?”——这个插件治好了我的精神
java·后端
煤烦恼2 小时前
Spark-SQL核心编程(二)
大数据·sql·spark