#4 InterceCzęść NR.4

W poprzednim wpisie omówiłem, czym jest intercepcja w programowaniu. Chociaż jak zajrzysz do Googli, to możesz zobaczyć, że słowo to często jest używane w footballu amerykańskim.

Poprzednim razem skorzystaliśmy z Castle.Windsor i DynamicProxy.

Teraz zrobię to samo tylko przy użyciu PostSharpa. Wpis będzie krótki, gdyż omówienie techniczne zostało zrobione wcześniej.

Aby użyć PostSharpa musimy stworzyć klasę aspektową.

Tym razem klasa ta dziedziczy po MethodInterceptionAspect.

[Serializable]
public class MyInterceptorAspect : MethodInterceptionAspect
{
    public override void OnInvoke
        (MethodInterceptionArgs args)
    {
        args.Proceed();
    }
}

Aby aspekt mógł wykonać metodę bazową musimy skorzystać z metody Proceed.

Postanowiłem wkleić kod z poprzedniego wpisu.

Jak się okazało wiele zmian polegało tylko na zmianie nazw zmiennych.

[Serializable]
public class MyInterceptorAspect 
    : MethodInterceptionAspect
{
    public override void OnInvoke
        (MethodInterceptionArgs args)
    {
        WriteMessage(args, "Before method ", 
            ConsoleColor.DarkYellow);
        args.Proceed();
        WriteMessage(args, "End method ",
            ConsoleColor.Yellow);
    }

    public void WriteMessage(MethodInterceptionArgs 
        invocation, string message, ConsoleColor color)
    {
        Console.ForegroundColor = color;
        Console.WriteLine(message +
            invocation.Method.DeclaringType.Name + "." + invocation.Method.Name
            + " in " + invocation.Method.Module.Name);
        Console.ForegroundColor = ConsoleColor.Gray;
    }
}

Kod działa tak samo.

image

Analogicznie do poprzedniego przykładu mogę wykonać metodę biznesową wiele razy w moim aspekcie.

[public override void OnInvoke
    (MethodInterceptionArgs args)
{
    WriteMessage(args, "Before method ", 
        ConsoleColor.DarkYellow);

    Random r = new Random(Guid.NewGuid().GetHashCode());

    for (int i = 0; i < r.Next(1,10); i++)
    {
        args.Proceed();
    }

    WriteMessage(args, "End method ",
        ConsoleColor.Yellow);
}

image

Mogę też obsłużyć błąd w moim aspekcie jak i klauzurę finally.

Teraz nie będę musiał do każdej klasy biznesowej pisać słów kluczowych try-catch-finally.

[[Serializable]
public class MyInterceptorAspect 
    : MethodInterceptionAspect
{
    public override void OnInvoke
        (MethodInterceptionArgs args)
    {
        WriteMessage(args, "Before method ", ConsoleColor.DarkYellow);
        try
        {
            args.Proceed();
        }
        catch (Exception ex)
        {
            WriteMessage(args, "Error " + ex.Message + " ", ConsoleColor.Red);
        }
        finally
        {
            WriteMessage(args, "End method ", ConsoleColor.Green);
        }
    }

    public void WriteMessage(MethodInterceptionArgs 
        invocation, string message, ConsoleColor color)
    {
        Console.ForegroundColor = color;
        Console.WriteLine(message +
            invocation.Method.DeclaringType.Name + "." + invocation.Method.Name
            + " in " + invocation.Method.Module.Name);
        Console.ForegroundColor = ConsoleColor.Gray;
    }
}

Dodajmy do klasy biznesowej wyjątek, by zobaczyć jak to działa w praktyce.

public class MotherFBussinesClass
{
    [MyInterceptorAspect]
    public void Method1()
    {
        throw new ArgumentException("Error lol");
        Console.WriteLine("I am MotherFBussinesClass");
    }
}

Aplikacja działa tak samo jak przykład Castle.Windsor.

image

W następnym wpisie obejrzymy bardziej zawansowane przykłady AOP.