-
Notifications
You must be signed in to change notification settings - Fork 113
Aspects.Counter
Igor Tkachev edited this page May 20, 2016
·
1 revision
This aspect helps to collect statistical information for the members it is applied to.
using System;
using System.Reflection;
using NUnit.Framework;
using BLToolkit.Aspects;
using BLToolkit.Reflection;
namespace HowTo.Aspects
{
[TestFixture]
public class CounterAspectTest
{
public abstract class TestClass
{
// This is a method we collect statistic for.
// Actually the entire class or even a base class
// can be decorated with the attribute.
//
[Counter]
public virtual void TestMethod()
{
}
}
[Test]
public void Test()
{
TestClass t = TypeAccessor<TestClass>.CreateInstance();
for (int i = 0; i < 10; i++)
t.TestMethod();
MethodInfo methodInfo = typeof(TestClass).GetMethod("TestMethod");
MethodCallCounter counter = CounterAspect.GetCounter(methodInfo);
Assert.AreEqual(10, counter.TotalCount);
Console.WriteLine(@"
Method : {0}.{1}
TotalCount : {2}
ExceptionCount : {3}
CachedCount : {4}
CurrentCalls : {5}
TotalTime : {6}
MinTime : {7}
MaxTime : {8}
AverageTime : {9}
",
counter.MethodInfo.DeclaringType.Name,
counter.MethodInfo.Name,
counter.TotalCount, // total actual calls (no cached calls)
counter.ExceptionCount, // calls with exceptions
counter.CachedCount, // cached calls
counter.CurrentCalls.Count, // current calls (make sense for multithreading)
counter.TotalTime, // total work time
counter.MinTime, // min call time
counter.MaxTime, // max call time
counter.AverageTime); // average call time
}
}
}
BLToolkit type builder will generate the following for the class above:
[BLToolkitGenerated]
public sealed class TestClass : CounterAspectTest.TestClass
{
private static CallMethodInfo _methodInfo;
private static IInterceptor _interceptor;
public override void TestMethod()
{
if (_methodInfo == null)
{
_methodInfo = new CallMethodInfo((MethodInfo)MethodBase.GetCurrentMethod());
}
InterceptCallInfo info = new InterceptCallInfo();
try
{
info.Object = this;
info.CallMethodInfo = _methodInfo;
info.InterceptResult = InterceptResult.Continue;
info.InterceptType = InterceptType.BeforeCall;
if (_interceptor == null)
{
_interceptor = new CounterAspect();
_interceptor.Init(_methodInfo, null);
}
// 'BeforeCall' creates or gets a counter for the method and
// registers the current call.
// See the [link][file]Aspects/CounterAspect.cs[/file]CounterAspect.BeforeCall[/link] method for details.
//
_interceptor.Intercept(info);
if (info.InterceptResult != InterceptResult.Return)
{
// Target method call.
//
base.TestMethod();
}
}
catch (Exception exception)
{
info.Exception = exception;
info.InterceptResult = InterceptResult.Continue;
info.InterceptType = InterceptType.OnCatch;
// 'OnCatch' is required to count calls with exceptions.
//
_interceptor.Intercept(info);
if (info.InterceptResult != InterceptResult.Return)
{
throw;
}
}
finally
{
info.InterceptResult = InterceptResult.Continue;
info.InterceptType = InterceptType.OnFinally;
// 'OnFinally' step adds statistic to the method counter.
// See the [link][file]Aspects/CounterAspect.cs[/file]CounterAspect.OnFinally[/link] method for details.
//
_interceptor.Intercept(info);
}
}
}
The following picture shows the information collected for data accessors of the BLToolkit.Demo.Asp.Net project.