我需要測量我的winform.net應用程序中每個方法的執行持續時間。輸出到文件中。庫來測量.NET中每個方法的執行持續時間winform應用程序
而不是我需要把代碼的開始時間和結束時間放到每個.NET方法,我想知道是否有一個庫可以通過改變配置文件來打開/關閉來做到這一點。
謝謝。
Koronx
我需要測量我的winform.net應用程序中每個方法的執行持續時間。輸出到文件中。庫來測量.NET中每個方法的執行持續時間winform應用程序
而不是我需要把代碼的開始時間和結束時間放到每個.NET方法,我想知道是否有一個庫可以通過改變配置文件來打開/關閉來做到這一點。
謝謝。
Koronx
嘗試這樣的方式,可以很容易地添加這個橫切關注點設計應用程序。例如,把業務邏輯/行爲用於單次使用的情況下在一類,並用一個通用的接口裝飾它:
public interface IUseCaseHandler<TUseCase>
{
void Handle(TUseCase useCase);
}
用例的定義是一個簡單的DTO(數據傳輸對象):
public class MoveCustomerUseCase
{
public int CustomerId { get; set; }
public Address Address { get; set; }
}
實現可以是這樣的:
public class MoveCustomerUseCaseHandler
: IUseCaseHandler<MoveCustomerUseCase>
{
public void Handle(MoveCustomerUseCase useCase)
{
// todo: business logic
}
}
你是怎麼獲得嗎?那麼,當全部使用辦案實現IUseCaseHandler<T>
界面,你可以寫一個decorator所有的處理程序:
public class DurationMeasuringUseCaseHandlerDecorator<TUseCase>
: IUseCaseHandler<TUseCase>
{
private readonly IUseCaseHandler<TUseCase> decoratedInstance;
private readonly ILogger logger;
public DurationMeasuringUseCaseHandlerDecorator(
IUseCaseHandler<TUseCase> decoratedInstance,
ILogger logger)
{
this.decoratedInstance = decoratedInstance;
this.logger = logger;
}
public void Handle(TUseCase useCase)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
try
{
// call the real use case handler
this.decoratedInstance.Handle(useCase);
}
finally
{
this.logger.Log(typeof(TUseCase).Name +
" executed in " +
stopwatch.ElapsedMiliseconds + " ms.");
}
}
}
這似乎是一個很大的代碼記錄的一點點,不是嗎?實際上,並非如此。這是您唯一需要編寫代碼的時間,並且您不必更改任何用例處理程序來添加度量。你可以只包住這樣所有的處理程序:
// Composing the object graph
IUseCaseHandler<MoveCustomerUseCase> handler =
newMoveCustomerUseCaseHandler(
new MoveCustomerUseCaseHandler(),
new Logger());
// Using the object (somewhere else in the code)
handler.Handle(new MoveCustomerUseCase { CustomerId = id, Address = adr });
但現在我們仍然必須我們想用這種每次連接到一起的對象圖?這是IoC容器進入圖片的地方。例如,使用Simple Injector,它需要一行代碼在系統中註冊的所有的用例的處理程序:
通過所有公共類型的組件中的RegisterManyForOpenGeneric方法迭代,並登記該實施IUseCaseHandler<T>
接口的所有具體類型,通過其封閉的通用表示(如IUseCaseHandler<MoveCustomerUseCase>
)。
包裝紙的所有處理與裝飾只是另一種的一行:
container.RegisterDecorator(typeof(IUseCaseHandler<>),
typeof(DurationMeasuringUseCaseHandlerDecorator<>));
有了這個配置,我們可以要求container
爲IUseCaseHandler<MoveCustomerUseCase>
,它將返回作爲MoveCustomerUseCaseHandler
包裹着DurationMeasuringUseCaseHandlerDecorator<MoveCustomerUseCase>
:
var handler =
container.GetInstance<IUseCaseHandler<MoveCustomerUseCase>>();
handler.Handle(new MoveCustomerUseCase
{
CustomerId = id, Address = adr
});
您可以使用C#的AOP庫,如postsharp。從postsharp文檔
修改例如:
/// <summary>
/// Aspect that, when applied on a method, emits a trace message before and
/// after the method execution.
/// </summary>
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
private string methodName;
private DateTime startTime;
/// <summary>
/// Method executed at build time. Initializes the aspect instance. After the execution
/// of <see cref="CompileTimeInitialize"/>, the aspect is serialized as a managed
/// resource inside the transformed assembly, and deserialized at runtime.
/// </summary>
/// <param name="method">Method to which the current aspect instance
/// has been applied.</param>
/// <param name="aspectInfo">Unused.</param>
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
this.methodName = method.DeclaringType.FullName + "." + method.Name;
}
/// <summary>
/// Method invoked before the execution of the method to which the current
/// aspect is applied.
/// </summary>
/// <param name="args">Unused.</param>
public override void OnEntry(MethodExecutionArgs args)
{
startTime = DateTime.Now;
Trace.TraceInformation("{0}: Enter", this.methodName);
Trace.Indent();
}
/// <summary>
/// Method invoked after successfull execution of the method to which the current
/// aspect is applied.
/// </summary>
/// <param name="args">Unused.</param>
public override void OnSuccess(MethodExecutionArgs args)
{
Trace.Unindent();
var duration = DateTime.Now - startTime;
Trace.TraceInformation("{0}: Success, Duration: {1}ms", this.methodName, duration.TotalMilliseconds);
}
}
要在項目中應用此每個方法,你只需要編輯的程序集信息。cs並添加:
[assembly: SomeNamespace.TraceAttribute()]
這是積極的一面,它是完全無創的,不需要對現有代碼進行更改。
不要使用代碼編織,使用良好的設計;-) – Steven
如果你有一個可怕的遺留應用程序,你在設計中沒有任何說法 - AOP可以是非常有用的。 – Vedran