C# 实现调用函数,打印日志(通过反射代理、非IOC)

发布于:2024-10-16 ⋅ 阅读:(119) ⋅ 点赞:(0)

在这里插入图片描述

🎈个人主页:靓仔很忙i
💻B 站主页:👉B站👈
🎉欢迎 👍点赞✍评论⭐收藏
🤗收录专栏:C#
🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!


需求:对于不方便debug的程序,查看日志是一个特别好的调试方式,但是在.net framework中,想实现面向切面打印日志特别困难。有人可能会想到使用Castle,使用Castle确实ok。但它需要依赖注入,需要框架去托管所有需要AOP的对象,系统中还有很多静态类,想实现这些都类的日志打印,我还需要去包装类库中的所有的静态类。这显然不现实,本文就是为了解决这个问题而写。

解决方案:为此,笔者写了一个Logger类,提供了CallStatic,CallMethod方式分别去调用方法,调用方法的时候,打印日志。调用思路也很简单,直接调用就行,需要调用的方法,通过参数传递即可。废话不多说,直接上干货。

  • 程序需要三个文件
    在这里插入图片描述
    • Logger:日志类
    • MyService: 测试使用的方法
    • Program: 入口
  • Logger文件
    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;

    namespace AutoTemplate.log
    {
        public static class Logger
        {
            public static void CallStatic(Expression<Action> expression)
            {
                var methodInfo = (MethodCallExpression)expression.Body;
                var method = GetMethodInfo(methodInfo);
                var parameters = GetParameters(methodInfo);
                PrintStartLog(method, parameters);
                method.Invoke(null, parameters);
                PrintEndLog(method);
            }
            public static T CallStatic<T>(Expression<Func<T>> expression)
            {
                var methodInfo = (MethodCallExpression)expression.Body;
                var method = GetMethodInfo(methodInfo);
                var parameters = GetParameters(methodInfo);

                PrintStartLog(method, parameters);
                var result = (T)method.Invoke(null, parameters);
                PrintEndLog(method);
                return result;
            }

            public static void CallMethod<T>(this T instance, Expression<Action<T>> expression)
            {
                var methodInfo = (MethodCallExpression)expression.Body;
                var method = GetMethodInfo(methodInfo);
                var parameters = GetParameters(methodInfo);

                PrintStartLog(method, parameters);
                method.Invoke(instance, parameters);
                PrintEndLog(method);
            }

            public static TResult CallMethod<T, TResult>(this T instance, Expression<Func<T, TResult>> expression)
            {
                var methodInfo = (MethodCallExpression)expression.Body;
                var method = GetMethodInfo(methodInfo);
                var parameters = GetParameters(methodInfo);

                PrintStartLog(method, parameters);
                var result = (TResult)method.Invoke(instance, parameters);
                PrintEndLog(method);

                return result;
            }

            private static MethodInfo GetMethodInfo(MethodCallExpression methodCall)
            {
                return methodCall.Method;
            }

            private static object[] GetParameters(MethodCallExpression methodCall)
            {
                object[] parameters = methodCall.Arguments.Count > 0
                   ? methodCall.Arguments.Select(arg => Expression.Lambda(arg).Compile().DynamicInvoke()).ToArray()
                   : Array.Empty<object>();
                return parameters;
            }

            private static void PrintStartLog(MethodInfo method, object[] parameters) {
                Console.WriteLine($"==========================================");
                Console.WriteLine($"[Log Start]开始调用方法: {method.Name}({string.Join(", ", parameters)})");
            }

            private static void PrintEndLog(MethodInfo method)
            {
                Console.WriteLine($"[Log End]方法调用成功: {method.Name}");
            }
        }
    }
  • MyService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoTemplate
{
    public class MyService
    {
        public static void NoArgNoResultStaticMethod()
        {
            Console.WriteLine("静态方法:无参无返回值");
        }

        public static void OneArgStaticMethod(string a)
        {
            Console.WriteLine($"静态方法:一个参数无返回值,参数:{a}");
        }

        public static string ResultStaticMethod()
        {
            Console.WriteLine($"静态方法:无参数有返回值,返回值:hello");
            return "这是ResultStaticMethod返回值";
        }

        public void NoArgNoResultMethod()
        {
            Console.WriteLine("方法:无参无返回值");
        }

        public void OneArgMethod(string aaa)
        {
            Console.WriteLine($"方法:一个参数无返回值,参数:{aaa}");
        }

        public int ReturnMethod()
        {
            Console.WriteLine($"方法:无参一个返回值");
            return 0;
        }

        public string OneArgReturnMethod(string e)
        {
            Console.WriteLine($"方法:一个参数一个返回值,参数:{e}");
            return "这是OneArgReturnMethod返回值";
        }

        public string ThreeArgOneResultMethod(string e,float f,int g)
        {
            Console.WriteLine($"方法:三个参数一个返回值,参数:{e},{f},{g}");
            return "这是ThreeArgOneResultMethod返回值";
        }
    }
}

  • Program
using AutoTemplate.log;
using FlaUI.UIA3;
using PATool.Core.Automation;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;

namespace AutoTemplate
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //静态方法调用
            Logger.CallStatic(() => MyService.NoArgNoResultStaticMethod());
            Logger.CallStatic(() => MyService.OneArgStaticMethod("abc"));
            var staticRes= Logger.CallStatic(() => MyService.ResultStaticMethod());
            var processRes = Logger.CallStatic(() => Process.Start("notepad++"));

            //对象方法调用
            var myService = new MyService();
            myService.CallMethod(s => s.NoArgNoResultMethod());
            myService.CallMethod(s => s.OneArgMethod("hello"));
            var res1=myService.CallMethod(s => s.ReturnMethod());
            var res2=myService.CallMethod(s => s.OneArgReturnMethod("xlwang"));
            var res3 = myService.CallMethod(s => s.ThreeArgOneResultMethod("xlwang",1.2f,5));

        }
    }
}
  • 运行结果
    在这里插入图片描述

网站公告

今日签到

点亮在社区的每一天
去签到