AOP interceptors
От: IT Россия linq2db.com
Дата: 12.06.06 03:37
Оценка: 134 (8)
Добавил базовый перехватчик и несколько типовых аспектов на его базе: 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>>
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.