#2 PostSharpCzęść NR.2

Czas na proste demo AOP przy użyciu PostSharp i IL Code Weaving.

W poprzednim wpisie omówiłem na czym polega AOP. Jeśli jeszcze wszystkiego nie rozumiesz, to spokojnie dopiero patrząc na konkretne przykłady, sprawa z AOP staje się jasna jak żarówka.

Projekt Demo zaczynamy od utworzenia nowego projektu w Visual Studio.  Demo będzie proste, dlatego wystarczy nam aplikacja konsolowa.

Console Application

Czas do naszego projektu dodać bibliotekę PostSharp.

NuGet

W oknie NuGet wpisz “PostSharp” i zainstaluj paczkę do swojego projektu.

postSharp

PostSharp jest płatnym narzędziem. Przykłady AOP, które zastosuję jednak nie wymagają kompletnej wersji. Dlatego w oknie wybierz “Use PostSharp Express”.

Na temat tego, co i jaka wersja PostSharpa potrafi, możesz przeczytać tutaj:

https://www.postsharp.net/purchase

postSharp Licence

Teraz, gdy referencja do PostSharpa została zainstalowana możemy napisać klasy biznesowe, które są tak zawansowane, że  wyświetlają napis HelloWorld.

public class MotherFBussinesClass
{
    public void Method1()
    {
        Console.WriteLine("I am MotherFBussinesClass");
    }
}

public class AnotherBussinesClass
{
    public void Method1()
    {
        Console.WriteLine("I am AnotherBussinesClass");
    }
}

Użyjemy je w prosty sposób. Stworzymy obiekty biznesowe i wywołamy ich metody.

namespace PostSharpHello
{
    class Program
    {
        static void Main(string[] args)
        {
            var obj = new MotherFBussinesClass();
            var obj2 = new AnotherBussinesClass();

            obj.Method1();
            obj2.Method1();
        }
    }
}

Gdy spróbujesz skompilować aplikację z bibliotekami PostSharp. Visual Studio przypomni ci, że same biblioteki nie wystarczą i trzeba zainstalować dodatek do Visual Studio.

W końcu jak kompilator .NET ma wstrzykiwać po procesie kompilacyjnym kod, jeśli on nie ma takiego wbudowanego mechanizmu.

postSharp Licence dodatek

Zainstaluj wiec dodatek do Visual Studio.

https://visualstudiogallery.msdn.microsoft.com/a058d5d3-e654-43f8-a308-c3bdfdd0be4a

Po uruchomieniu zobaczysz okno Tutorialu, ale zignoruj go na razie.

postSharp Tutorial

Teraz kod może się skompilować.

Console

Na razie nie dzieje się żadna magia AOP, więc ją dodajmy.

Stwórzmy nasz pierwszy Aspekt.

Klasa Aspektowa PostSharpa musi być zserializowana. Wynika to z tego, że PostSharp dodaje aspekt w procesie po kompilacyjnym. Aspekty muszą być istnieć pomiędzy czasem kompilacji i czasem uruchomienia.

using PostSharp.Aspects;
using System;

namespace PostSharpHello
{
    [Serializable]
    public class MyAspect : OnMethodBoundaryAspect
    {
    }
}

Nasz pierwszy aspekt dziedziczy po klasie “OnMethodBoundaryAspect”. Oznacza to, że możemy teraz się bawić kodem wewnątrz każdej metody w naszej aplikacji.

Zacznij więc krojenie i ucinanie.

Gdzie możemy to zrobić. Zobaczmy jakie metody możemy przeciążyć.

OnMethodBoundaryAspect

Każda metoda ma punkt łączenia jak:

  • Przed wykonaniem metody  - OnEntry
  • Po wykonaniu metody – OnExit
  • Kiedy metoda wyrzuci wyjątek – OnException
  • Kiedy metoda wykona się bez wyjątku – OnSuccess
  • Kiedy metoda wraca do wykonywania po słowie kluczowym Yield albo await – onResume
  • Kiedy metoda następuje na słowo kluczowe  yeild i await – OnYeild

Jest ich trochę więcej niż omówiłem w poprzednim wpisie. Szerszy opis metod znajduje się tutaj.

http://doc.postsharp.net/t_postsharp_aspects_onmethodboundaryaspect

PostSharp ma dobrą dokumentację.

Wykorzystajmy więc metody OnEntry i OnExist i dodajmy kod, który się wykona przed wywołaniem metod biznesowych i po.

[Serializable]
public class MyAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine("Before Method " + args.Method.Name);
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine("After Method " + args.Method.Name);
    }
}

Teraz, gdy mamy klasę Aspektu musimy jakoś powiedzieć PostSharpowi, że chcemy je wywołać w naszych metodach.

Dla uproszczenia skorzystałem z atrybutów, ale uwaga PostSharp nie jest takim słabym narzędziem, byśmy musieli wklejać atrybuty do każdej istniejącej metody w naszym kodzie. Na razie chcę utrzymać przykład w prostocie.

public class MotherFBussinesClass
{
    [MyAspect]
    public void Method1()
    {
        Console.WriteLine("I am MotherFBussinesClass");
    }
}

public class AnotherBussinesClass
{
    [MyAspect]
    public void Method1()
    {
        Console.WriteLine("I am AnotherBussinesClass");
    }
}

Jak widzimy Aspekty działają.

OnMethodBoundaryAspect result

Teraz pytanie co mogę fajnego zrobić wewnątrz tych metod jak OnEntry.

Parametr args zawiera informację:

  • O metodzie
  • O argumentach przesłanych do metody
  • O wyjątku jeśli wystąpił
  • O wartości zwracanej jeśli ona jest
  • i o samej instancji klasy, która posiada tą metodę.

To wszystko daje spore możliwości do cięcia kodu na Aspekty.

args OnMethodBoundaryAspect result

Oto ulepszony kod klasy Aspektowej. Korzystając z właściwości Method jestem w stanie pobrać informacje na temat nazwy klasy, która wywołuje tę metodę. Mogę też pobrać informację na temat modułu, w którym znajduje się ta metoda.

[Serializable]
public class MyAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.ForegroundColor = ConsoleColor.DarkYellow;
        Console.WriteLine("Before Method " + 
            args.Method.DeclaringType.Name + " "+ args.Method.Name
            + "in " + args.Method.Module.Name);
        Console.ForegroundColor = ConsoleColor.Gray;
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("After Method " +
            args.Method.DeclaringType.Name + " " + args.Method.Name
            + "in " + args.Method.Module.Name);
        Console.ForegroundColor = ConsoleColor.Gray;
    }
}

Tekst ciemno i jasno żółty obrazuje działanie kodu w klasach aspektowych.

Console

Ten prosty przykład demo jest imponujący. Zauważ, że dodaliśmy kod do metod biznesowych, wcale ich nie zmieniając.

Musiałeś dodać atrybut, ale nawet to nie jest potrzebne.

Oczywiście PostSharp i IL Code Weaving nie jest jedyną techniką implementacyjną AOP.

Mamy jeszcze rozwiązanie CastleWindsor polegające na tworzeniu dynamicznych dekoratorów;