基于AOP+Log4Net+AutoFac日志框架

news2025/4/13 5:33:08

1.项目概述

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

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 构建容器,注册接口及其实现类(如 IService 与 ServiceIService2 与 Service2 )以及窗口类(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 的特性来呈现用户界面和交互逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python推箱子游戏

,--^----------,--------,-----,-------^--,-------- 作者 yty---------------------------^----------_,-------, _________________________XXXXXX XXXXXX XXXXXX ______(XXXXXXXXXXXX(________(------ 0 [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,…

华为hcie证书的有效期怎么判断?

在ICT行业&#xff0c;华为HCIE证书堪称含金量极高的“敲门砖”&#xff0c;拥有它往往意味着在职场上更上一层楼。然而&#xff0c;很多人在辛苦考取HCIE证书后&#xff0c;却对其有效期相关事宜一知半解。今天&#xff0c;咱们就来好好唠唠华为HCIE证书的有效期怎么判断这个关…

PowerBI 条形图显示数值和百分比

数据表: 三个度量值 销售额 SUM(销量表[销售量])//注意, 因为Y轴显示的产品&#xff0c;会被筛选&#xff0c;所以用ALLSELECTED来获取当前筛选条件下&#xff0c;Y轴显示的产品 百分比 FORMAT(DIVIDE([销售额],CALCULATE([销售额],ALLSELECTED(销量表[产品编码]))),"0…

基于YOLOv8的火车轨道检测识别系统:技术实现与应用前景

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 引言&#xff1a;火车轨道检测领域概述 铁路运输作为国民经济的大动脉&#xff0c;其安全运行至关重要…

css使用mix-blend-mode的值difference实现内容和父节点反色

1. 使用场景 往往开发过程中&#xff0c;经常遇到产品说你这个背景图和文字颜色太接近了&#xff0c;能不能适配下背景图&#xff0c;让用户能够看清具体内容是啥。 这么说吧&#xff0c;这种需求场景非常合理&#xff0c;因为你做开发就是要给用户一个交代&#xff0c;给他们…

Pytest多环境切换实战:测试框架配置的最佳实践!

你是否也遇到过这种情况&#xff1a;本地测试通过&#xff0c;一到测试环境就翻车&#xff1f;环境变量错乱、接口地址混乱、数据源配置丢失……这些「环境切换」问题简直像定时炸弹&#xff0c;随时引爆你的测试流程&#xff01; 测试人员每天都跟不同的环境打交道&#xff0…

单细胞多组学及空间组学数据分析与应用

一、引言 生命科学研究正处于快速发展的阶段&#xff0c;随着技术的不断革新&#xff0c;对生物系统的理解也在逐步深入到单细胞和空间层面。单细胞多组学及空间组学技术应运而生&#xff0c;它们突破了传统研究手段在细胞异质性和空间结构解析上的局限&#xff0c;为我们打开…

[ctfshow web入门] web39

信息收集 题目发生了微妙的变化&#xff0c;只过滤flag&#xff0c;include后固定跟上了.php。且没有了echo $flag;&#xff0c;虽说本来就没什么用 if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/flag/i", $c)){include($c.".php");} }else{…

HarmonyOS-ArkUI 装饰器V2 @ObservedV2与@Trace装饰器

参考文档: 文档中心https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/arkts-new-observedv2-and-trace-V14#trace%E8%A3%85%E9%A5%B0%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84由于V2的装饰器比V1的装饰器更加易用,尽管学习的过程中用到的都是V1的装饰器,但…

基于ImGui+FFmpeg实现播放器

基于ImGuiFFmpeg实现播放器 演示&#xff1a; ImGui播放器 继续研究FFmpeg&#xff0c;之前做了一个SDL的播放器&#xff0c;发现SDL的可视化UI界面的功能稍微差了点&#xff0c;所以今天我们换了一个新的工具&#xff0c;也就是ImGui。 ImGui官方文档&#xff1a;https://g…

python的web框架flask(hello,world版)

问题 最近需要基于一个开源项目进行二次开发&#xff0c;但是&#xff0c;现在的我主修java&#xff0c;从来没有接触过python的web开发。所以&#xff0c;我现在需要学习一下flask的hello&#xff0c;world。 python版本选择 通过这个Python版本状态页面Status of Python v…

Java面试39-Zookeeper中的Watch机制的原理

Zookeeper是一个分布式协调组件&#xff0c;为分布式架构下的多个应用组件提供了顺序访问控制能力。它的数据存储采用了类似于文件系统的树形结构&#xff0c;以节点的方式来管理存储在Zookeeper上的数据。 Zookeeper提供了一个Watch机制&#xff0c;可以让客户端感知到Zooke…

同时打开多个Microchip MPLAB X IDE

0.引用 Microchip 32位MCU CAN驱动图文教程-附源码 - 哔哩哔哩 https://bbs.21ic.com/icview-3391426-1-1.html https://bbs.21ic.com/icview-3393632-1-1.html 1.前言 工作中接触到使用Microchip 的 MPLAB X IDE 开发工具&#xff0c;使用的MCU是Microchip SAMD21J18A MCU…

达梦数据库使用druid提示:dbType not support : dm

简单处理&#xff1a; 移除wall即可 &#xff08;但是用druid那都希望能用上它的功能的&#xff0c;不然为什么不用其他没带检查的jdbc呢。&#xff09; 中等复杂处理&#xff1a; druid 是阿里开源的项目&#xff0c;所以去github上找对应版本的源码下载&#xff1a;https:/…

[定位器]晶艺LA1823,4.5V~100V, 3.5A,替换MP9487,MP9486A,启烨科技

Features  4.5V to 100V Wide Input Range  3.5A Typical Peak Current Limit  Integrated 500mΩ low resistance high side power MOS.  Constant On Time Control with Constant Switching Frequency.  180μA Low Quiescent Current  150kHz/240kHz/420kHz Swi…

难度偏低,25西电人工智能学院821、833、834考研录取情况

1、人工智能学院各个方向 2、人工智能学院近三年复试分数线对比 学长、学姐分析 由表可看出&#xff1a; 1、智能院25年院线相对于24年院线 全部专业下降比较多&#xff0c;其中控制科学与工程下降20分&#xff0c;计算机科学与技术下降20分&#xff0c;计算机技术[专硕]下降…

使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第七讲)

这一期来讲解与文本框配套使用的键盘&#xff0c;以及键盘如何在项目中开启。 打开GUI_guider软件平台&#xff0c;在左上角点开工程选项&#xff0c;在该栏目的最下方点击系统设置。 随后在系统设置界面中点击项目选项&#xff0c;选择显示键盘。 在该界面中可以设置键盘文字…

通过AWS EKS 生成并部署容器化应用

今天给大家分享一个实战例子&#xff0c;如何在EKS上创建容器化应用并通过ALB来发布。先介绍一下几个基本概念&#xff1a; IAM, OpenID Connect (OIDC) 2014 年&#xff0c;AWS Identity and Access Management 增加了使用 OpenID Connect (OIDC) 的联合身份支持。此功能允许…

nginx入门,部署静态资源,反向代理,负载均衡使用

Nginx在linux上部署静态资源 概念介绍 Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在服务端真实存在&#xff0c;并且能够直接展示的一些文件&#xff0c;比如常见的html页面、css文件、js文件、图片、视频等资源。 相对于Tomcat&#xff0c;Nginx处理…

智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案

智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子&#xff08;Coze&#xff09;的智能解决方案 数据驱动餐饮管理&#xff0c;让每一餐都是营养与经济的完美平衡&#xff01; “智膳优选”通过整合飞书与Coze&#xff0c;将数据智能引入校园餐饮管理&#xff0…