Добавил базовый перехватчик и несколько типовых аспектов на его базе: LoggingAspect, CacheAspect и CounterAspect. Хотел ещё сделать PermissionAspect, но там получается всё достаточно интимно и как сделать общее решение не понятно.
Использование.
LogginAspect:
public abstract class TestClass
{
// Лог конкретного метода.
//
[Log]
public virtual void Test(int p1)
{
}
// Логировать вызовы, выполняющиеся более 0.5 сек.
//
[Log("MinCallTime=500")]
public virtual void Test(int p1)
{
}
}
// Лог всех методов класса.
//
[Log]
public abstract class TestClass
{
public virtual void Test1(int p1)
{
}
// Отключить лог для данного метода
//
[NoLog]
public virtual void Test2(int p1)
{
}
}
void Test()
{
// Параметры, влияющие на все вызовы, исключая те, где эти параметры заданы явно.
//
LoggingAspect.LogParameters = true; // логировать значения параметров вызываемого метода. Умолчание - true.
LoggingAspect.LogExceptions = true; // логировать исключения. Умолчание - true.
LoggingAspect.MinCallTime = 1000; // логировать вызовы дольше 1 секунды. Умолчание - 0.
LoggingAspect.FileName = "log.txt"; // выводить в файл. Умолчание - null - Debug.WriteLine.
LoggingAspect.IsEnabled = false; // оключить лог. Умолчание - true.
TestClass t = TypeAccessor.CreateInstance<TestClass>();
t.Test(1);
}
CacheAspect кеширует результат вызова методов в зависимости от значения параметров. Кешируется возвращаемое значние и ref/out параметры.
public abstract class TestClass
{
// Кешировать результат вызова метода.
//
[Cache]
public virtual ArrayList Test(int p1)
{
return new ArrayList(p1);
}
}
// Кешировать результаты вызова всех методов класса на 1 секунду.
//
[Cache(1000)]
public abstract class TestClass
{
[NoCache]
public virtual void Test1(int p1)
{
}
}
void Test()
{
// Параметры, влияющие на все вызовы, исключая те, где эти параметры заданы явно.
//
CacheAspect.MaxCacheTime = 1000; // длительность кеширования. Умолчание - int.MaxValue.
CacheAspect.IsWeak = true; // использовать слабые ссылки. Умолчание - true.
CacheAspect.IsEnabled = false; // оключить кеширование. Умолчание - true.
TestClass t = TypeAccessor.CreateInstance<TestClass>();
t.Test(1);
}
CounterAspect собирает статистику по вызовам методов.
public abstract class TestClass
{
// Статистика вызовов метода.
//
[Counter]
public virtual ArrayList Test(int p1)
{
return new ArrayList(p1);
}
}
// Собирать статистику вызовов всех методов класса.
//
[Counter]
public abstract class TestClass
{
[NoCounter]
public virtual void Test1(int p1)
{
}
}
void Test()
{
// Параметры, влияющие на все вызовы, исключая те, где эти параметры заданы явно.
//
CounterAspect.IsEnabled = false; // оключить сбор статистики. Умолчание - true.
TestClass t = TypeAccessor.CreateInstance<TestClass>();
t.Test(1);
lock (CounterAspect.Counters.SyncRoot)
{
foreach (CounterAspect.Counter c in CounterAspect.Counters)
{
c.MethodInfo // метаданные метода
c.TotalTime // общее время выполнения всех завершённых вызовов
c.TotalCount // общее количество завершённых вызовов
c.CurrentCalls // текущие вызовы
// Здесь интерес могут представлять следующие поля
InterceptCallInfo ci = (InterceptCallInfo)c.CurrentCalls[0];
(IPrincipal)ci.Items["CurrentPrincipal"]; // кто вызвал метод
ci.BeginCallTime // когда
}
}
}
... << RSDN@Home 1.2.0 alpha rev. 0>>