niedziela, 29 czerwca 2014

[C#|Visual Studio] AOP: Method Interception

Opakowanie metody możemy wykonać zarówno w Castle.DynamicProxy jak i przez Postsharp. Oba podejścia nieco różnią się od siebie.

W przypadku Castle zakładamy, że będziemy korzystać z kontenera IoC. Mamy prosty interfejs IMyInterface oraz prosty typ MyType. Rozpoczynamy od stworzenia interceptora, który będzie logował zdarzenia. Musi on dziedziczyć po interfejsie IInterceptor z przestrzeni nazw IInterceptor. Interfejs ten wystawia metodę Intercept.

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("On Enter");
        try
        {
            invocation.Proceed();
        }
        catch (Exception)
        {
            Console.WriteLine("On Error");
            throw;
        }
        finally
        {
            Console.WriteLine("On Exit");
        }
    }
}

Pozostaje jeszcze skonfigurować odpowiednio kontener i można korzystać z typu opakowanego w intereceptor.

using (var windsorContainer = new WindsorContainer())
{
    windsorContainer.Register(Component.For<LoggingInterceptor>());
    windsorContainer.Register(Component.For<IMyInterface>()
                                    .ImplementedBy<MyType>()
                                    .Interceptors<LoggingInterceptor>());

    var type = windsorContainer.Resolve<IMyInterface>();

    type.Run();
}

W Postsharpie dziedziczymy po bazowej klasie OnMethodBoundaryAspect, która definiuje potrzebne nam metody wirtualne. Ważne, by nasz aspekt oznaczyć atrybutem Serializable.

[Serializable]
public class LoggingInterceptor2: OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine("On Entry");
        base.OnEntry(args);
    }

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine("On Error");
        base.OnException(args);
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine("On Exit");
        base.OnSuccess(args);
    }
}

Nasza klasa jest atrybutem, który możemy umieścić nad definicją dowolnej metody.

Brak komentarzy:

Prześlij komentarz