Pull to refresh

Аспектно-ориентированное программирование. PostSharp

Reading time3 min
Views12K
Аспектно-ориентированное программирование

АОП — парадигма программирования, в основе которой лежит идея выделения сквозной функциональсти в отдельные сущности — аспекты (aspects). Сквозной называют функциональсть, рассредоточенную по разным частям программы. В качестве примеров сквозной функциональности можно привести задачи логирования, трассировки, обработки исключений, проверки пред- и постусловий в контрактном программировании и проверки прав доступа. АОП может так же использоваться для решения задач защиты и многопоточности.

PostSharp

Фреймворк PostSharp — это реализация аспектно-ориентированного подхода для .NET. PostSharp в отличие от многих своих аналогов работает как пост-компилятор, то есть он вносит изменения в MSIL (Microsoft Intermediate Language).
PostSharp позволяет легко создавать атрибуты, которые меняют поведение методов, полей и типов. Для этого нужно унаследовать класс атрибута от одного из предоставляемых библиотекой базовых классов, реализовать его виртуальные методы и применить этот атрибут.


Пример 1:
using System;
using PostSharp.Aspects;

namespace HelloAspects
{
    class Program
    {
        private static void Main()
        {
            hello();
        }

        [SayGoodbye]
        private static void hello()
        {
            Console.WriteLine("Hello!");
        }
    }

    [Serializable]
    class SayGoodbyeAttribute : OnMethodBoundaryAspect
    {
        public override void OnExit(MethodExecutionArgs args)
        {
            Console.WriteLine("Goodbye.");
        }
    }
}

В результате на консоль будет выведено:

Hello!
Goodbye.

В данном примере показано, как при помощи атрибута SayGoodbye изменилось поведение метода hello().

Метод OnExit называют советом (advice), он всегда выполняется (даже если выпадет исключение, так как OnExit вызывается из блока finally) после тела метода, к которому применяется атрибут. Помимо него класс OnMethodBoundaryAspect предоставляет ещё три совета:
  • OnEntry — выполняется перед телом метода;
  • OnSuccess — выполняется после успешного выполнения тела метода;
  • OnException — выполнятся после тела метода в случае, если в методе выпало необработанное исключение.

Хотя пример 1 и иллюстрирует некоторые возможности PostSharp, от него мало практической пользы. В примере 2 показана реализация трассировки при помощи АОП.

Пример 2:
using System;
using System.Diagnostics;
using PostSharp.Aspects;

namespace HelloAspects
{
    class Program
    {
        private static void Main()
        {
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
            hello();
        }

        [Trace]
        private static void hello()
        {
            Console.WriteLine("Hello!");
        }
    }

    [Serializable]
    public class TraceAttribute : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
            Trace.WriteLine(string.Format("Entering {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name));
        }

        public override void OnExit(MethodExecutionArgs args)
        {
            Trace.WriteLine(string.Format("Leaving {0}.{1}.", args.Method.DeclaringType.Name, args.Method.Name));
        }
    }
}


В чём же преимущество использования АОП в данном примере? Представим, что у нас есть несколько классов, в каждом из которых много методов и нам необходимо реализовать трассировку. Если не использовать АОП, то придётся в теле каждого метода прописывать Trace.WriteLine… Используя же АОП мы выделяем эту сквозную функциональность в отдельную сущность (аспект) и применяем её к методам при помощи атрибута.

Разумеется, в PostSharp есть аспекты и помимо OnMethodBoundaryAspect:
  • EventInterceptionAspect
  • LocationInterceptionAspect
  • OnExceptionAspect
    и многие другие.

PostSharp — это удобный инструмент для внедрения АОП в программы, написанные с использованием среды .NET. АОП дополняет ООП, выделяя сквозную функциональсть в отдельные аспекты, избавляется от дублирования кода (принцип DRY – Don't Repeat Yourself) и упрощает архитектуру приложения.

P.S. Этот пост был написан на основе работы по учёбе, которую я делал в институте.
Tags:
Hubs:
+30
Comments24

Articles

Change theme settings