使用属性 (.net core) 测量方法执行时间
Measure method execution time using an attribute (.net core)
我对测量执行特定方法所需的时间很感兴趣。
我认为使用自定义属性而不是使用代码向 start/stop 秒表发送代码并发送到记录器会非常方便。如果我能用一个属性来装饰这个方法,那就太方便了!
我能够按照这篇文章创建自定义属性:
https://docs.microsoft.com/en-us/dotnet/standard/attributes/writing-custom-attributes
像这样:
public class MonitorExecutionTime : Attribute
{
private Stopwatch measureExecution;
// Start measuring on instantiation
public MonitorExecutionTime()
{
measureExecution = new Stopwatch();
measureExecution.Start();
}
// how do I hook into end invoke?
public MethodHasEnded()
{
measureExecution.Stop();
TimeSpan timeSpan = measureExecution.Elapsed;
Console.WriteLine("Time: {0}h {1}m {2}s {3}ms", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds);
}
}
但我不确定如何 "capture" 正在调用和结束调用执行点以启动秒表和停止秒表(以测量时间并记录它)。
有人在 .net 核心应用程序中采用过这种方法吗?在此先感谢您的指点!
.NET 中的属性不是包装器,因此您不能以那种方式使用它们。
您必须使用方法调用包装器,例如:
public class Service : IService
{
public void Exec() {
Wrap("Method Exec", () => {
// do something usefull
});
}
private void Wrap(string message, Action action)
{
var watch = Stopwatch.StartNew();
try
{
action();
}
finally
{
watch.Stop();
Console.WriteLine($"{message} executed in {watch.ElapsedMilliseconds} ms");
}
}
}
如果你想包装class或者接口的所有方法,你应该看看面向切面编程,例如这篇文章:https://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/
运行时不调用属性。但是您可以使用 Fody 之类的库进行程序集编织 - 在您的程序集编译成标有您的自定义属性的方法后自动添加代码。
其实已经有你想要实现的实现了- Method Timer
这是它的工作原理(copy/paste 来自文档)。您的代码:
public class MyClass
{
[Time]
public void MyMethod()
{
//Some code u are curious how long it takes
Console.WriteLine("Hello");
}
}
实际编译成最终汇编的是什么
public class MyClass
{
public void MyMethod()
{
var stopwatch = Stopwatch.StartNew();
try
{
//Some code u are curious how long it takes
Console.WriteLine("Hello");
}
finally
{
stopwatch.Stop();
Trace.WriteLine("MyClass.MyMethod " + stopwatch.ElapsedMilliseconds + "ms");
}
}
}
您可以编写自定义拦截器代码以避免使用 Trace.WriteLine 并按照您想要的方式进行记录。
@Igore-goyda - 你的 post 让我找到了我需要的东西。总结一下其他人 - 有两种方法可以拦截方法和 运行 一些自定义处理。通过代理或使用 IL 重写器。
我发现这篇文章很好地解释了:http://jeffbelback.me/posts/2015/06/01/principles-of-aop/
我认为 Proxy 方法最适合我(不喜欢我的代码在编译后被修改的概念),并且能够按照本文使用 Autofac 实施合适的解决方案:
https://nearsoft.com/blog/aspect-oriented-programming-aop-in-net-core-and-c-using-autofac-and-dynamicproxy/
Autofac 文档也帮助了我:
https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html?highlight=proxy
我对测量执行特定方法所需的时间很感兴趣。
我认为使用自定义属性而不是使用代码向 start/stop 秒表发送代码并发送到记录器会非常方便。如果我能用一个属性来装饰这个方法,那就太方便了!
我能够按照这篇文章创建自定义属性: https://docs.microsoft.com/en-us/dotnet/standard/attributes/writing-custom-attributes
像这样:
public class MonitorExecutionTime : Attribute
{
private Stopwatch measureExecution;
// Start measuring on instantiation
public MonitorExecutionTime()
{
measureExecution = new Stopwatch();
measureExecution.Start();
}
// how do I hook into end invoke?
public MethodHasEnded()
{
measureExecution.Stop();
TimeSpan timeSpan = measureExecution.Elapsed;
Console.WriteLine("Time: {0}h {1}m {2}s {3}ms", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds);
}
}
但我不确定如何 "capture" 正在调用和结束调用执行点以启动秒表和停止秒表(以测量时间并记录它)。
有人在 .net 核心应用程序中采用过这种方法吗?在此先感谢您的指点!
.NET 中的属性不是包装器,因此您不能以那种方式使用它们。 您必须使用方法调用包装器,例如:
public class Service : IService
{
public void Exec() {
Wrap("Method Exec", () => {
// do something usefull
});
}
private void Wrap(string message, Action action)
{
var watch = Stopwatch.StartNew();
try
{
action();
}
finally
{
watch.Stop();
Console.WriteLine($"{message} executed in {watch.ElapsedMilliseconds} ms");
}
}
}
如果你想包装class或者接口的所有方法,你应该看看面向切面编程,例如这篇文章:https://www.c-sharpcorner.com/article/aspect-oriented-programming-in-c-sharp-using-dispatchproxy/
运行时不调用属性。但是您可以使用 Fody 之类的库进行程序集编织 - 在您的程序集编译成标有您的自定义属性的方法后自动添加代码。
其实已经有你想要实现的实现了- Method Timer
这是它的工作原理(copy/paste 来自文档)。您的代码:
public class MyClass
{
[Time]
public void MyMethod()
{
//Some code u are curious how long it takes
Console.WriteLine("Hello");
}
}
实际编译成最终汇编的是什么
public class MyClass
{
public void MyMethod()
{
var stopwatch = Stopwatch.StartNew();
try
{
//Some code u are curious how long it takes
Console.WriteLine("Hello");
}
finally
{
stopwatch.Stop();
Trace.WriteLine("MyClass.MyMethod " + stopwatch.ElapsedMilliseconds + "ms");
}
}
}
您可以编写自定义拦截器代码以避免使用 Trace.WriteLine 并按照您想要的方式进行记录。
@Igore-goyda - 你的 post 让我找到了我需要的东西。总结一下其他人 - 有两种方法可以拦截方法和 运行 一些自定义处理。通过代理或使用 IL 重写器。
我发现这篇文章很好地解释了:http://jeffbelback.me/posts/2015/06/01/principles-of-aop/
我认为 Proxy 方法最适合我(不喜欢我的代码在编译后被修改的概念),并且能够按照本文使用 Autofac 实施合适的解决方案: https://nearsoft.com/blog/aspect-oriented-programming-aop-in-net-core-and-c-using-autofac-and-dynamicproxy/
Autofac 文档也帮助了我: https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html?highlight=proxy