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

51 天前
 irisdev
现在手上有个老的 mvc 项目,有些方法执行时间比较长,每次都是代码第一行 StopWatch 监控一下执行时间写入表里面监控下。不知道有没有办法像 python 的类装饰器函数一样在类或方法之前写个注解就可以监控执行时间的方案,.net 的 Attribute 似乎做不到这种运行时的监控。想了下可能有两个方案:

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

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

请教下各位大佬在.net framework 里面有没有遇到过类似的需求,有没有什么比较好的实现方案,谢谢回复
934 次点击
所在节点    C#
7 条回复
quan01994
51 天前
可以使用
APM 。
IOC + AOP 。
静态织入。
irisdev
51 天前
@quan01994 谢谢佬,我没太懂,我去了解一下
yuhuai
51 天前
说实话,如果是测试该用 benchmark.net ,但你现在属于是被你自己给误导了,你是想监控哪些函数执行时间长,这时候应该用 dotTrace 这种工具在压力下进行监测,可以直接按耗时进行排序,再针对性处理
yuhuai
51 天前
附加一下,上面的名称被识别为网址了,实际测试框架地址是这个 https://github.com/dotnet/BenchmarkDotNet
cxe2v
51 天前
我一问 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]
void 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
51 天前
@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
51 天前
@cxe2v gpt 的这段代码...给每个 controller 都包一层还不如直接写在每个方法里面。快不等于好

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1097239

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX