请教下 C#有没有办法用装饰器全局监控方法执行时间 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
irisdev
V2EX    C#

请教下 C#有没有办法用装饰器全局监控方法执行时间

  •  
  •   irisdev 300 天前 2312 次点击
    这是一个创建于 300 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在手上有个老的 mvc 项目,有些方法执行时间比较长,每次都是代码第一行 StopWatch 监控一下执行时间写入表里面监控下。不知道有没有办法像 python 的类装饰器函数一样在类或方法之前写个注解就可以监控执行时间的方案,.net 的 Attribute 似乎做不到这种运行时的监控。想了下可能有两个方案:

    1.写个方法传个委托,然后在委托执行前后执行一下 StopWatch ,把业务代码都传到这个委托里。但是这么做很不方便,貌似意义不大

    2..net 有个开源库 MethodTime.Fody ,加上一个[Time]特性就可以实现我想要的效果,但是内网环境,而且我不是 Leader ,不敢随便引入其他包

    请教下各位大佬在.net framework 里面有没有遇到过类似的需求,有没有什么比较好的实现方案,谢谢回复
    7 条回复    2024-12-13 17:41:56 +08:00
    quan01994
        1
    quan01994  
       300 天前   1
    可以使用
    APM 。
    IOC + AOP 。
    静态织入。
    irisdev
        2
    irisdev  
    OP
       300 天前 via Android
    @quan01994 谢谢佬,我没太懂,我去了解一下
    yuhuai
        3
    yuhuai  
       300 天前   1
    说实话,如果是测试该用 benchmark.net ,但你现在属于是被你自己给误导了,你是想监控哪些函数执行时间长,这时候应该用 dotTrace 这种工具在压力下进行监测,可以直接按耗时进行排序,再针对性处理
    yuhuai
        4
    yuhuai  
       300 天前   1
    附加一下,上面的名称被识别为网址了,实际测试框架地址是这个 https://github.com/dotnet/BenchmarkDotNet
    cxe2v
        5
    cxe2v  
       300 天前   1
    我一问 gpt ,代码就出来了,不比在这里问这些网友快?


    }

    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
    // 检查方法是否有 MeasureTimeAttribute
    if (targetMethod.GetCustomAttribute<MeasureTimeAttribute>() != null)
    {
    var stopwatch = Stopwatch.StartNew();
    try
    {
    // 执行实际方法
    return targetMethod.Invoke(_decorated, args);
    }
    finally
    {
    stopwatch.Stop();
    Console.WriteLine($"方法 {targetMethod.Name} 执行耗时: {stopwatch.ElapsedMilliseconds} ms");
    }
    }
    else
    {
    // 没有特性直接调用方法
    return targetMethod.Invoke(_decorated, args);
    }
    }
    }
    3. 应用到目标类
    csharp
    复制代码
    public interface IExampleService
    {
    [MeasureTime]
    vid DoSomething();

    void DoOtherThing();
    }

    public class ExampleService : IExampleService
    {
    public void DoSomething()
    {
    // 模拟耗时操作
    System.Threading.Thread.Sleep(100);
    Console.WriteLine("执行 DoSomething");
    }

    public void DoOtherThing()
    {
    Console.WriteLine("执行 DoOtherThing");
    }
    }
    4. 使用动态代理包装实例
    csharp
    复制代码
    class Program
    {
    static void Main()
    {
    var service = MethodInterceptor<IExampleService>.Create(new ExampleService());

    service.DoSomething(); // 记录耗时
    service.DoOtherThing(); // 不记录耗时
    }
    }
    cxe2v
        6
    cxe2v  
       300 天前   1
    @cxe2v

    1. 定义一个自定义特性
    创建一个特性类,用于标记需要记录耗时的方法:

    csharp
    复制代码
    [AttributeUsage(AttributeTargets.Method, Inherited = true)]
    public class MeasureTimeAttribute : Attribute
    {
    }
    2. 使用动态代理拦截方法调用
    通过 AOP (面向切面编程)的方式,例如使用 Castle DynamicProxy 或 DispatchProxy ,拦截方法的执行并记录耗时。

    使用 DispatchProxy 示例:
    csharp
    复制代码
    using System;
    using System.Diagnostics;
    using System.Reflection;

    public class MethodInterceptor<T> : DispatchProxy
    {
    private T _decorated;

    public static T Create(T decorated)
    {
    object proxy = Create<T, MethodInterceptor<T>>();
    ((MethodInterceptor<T>)proxy)._decorated = decorated;
    return (T)proxy;
    irisdev
        7
    irisdev  
    OP
       300 天前
    @cxe2v gpt 的这段代码...给每个 controller 都包一层还不如直接写在每个方法里面。快不等于好
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     878 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 20:28 PVG 04:28 LAX 13:28 JFK 16:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86