Pokazywanie postów oznaczonych etykietą casle windsor. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą casle windsor. Pokaż wszystkie posty

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.

wtorek, 9 kwietnia 2013

[IoC] Castle Windsor

Obok Unity, drugim interesującym kontenerem IoC jest Castle Windsor. Oba kontenery udostępniają całkiem podobne API, warto jednak znać podstawowe różnice. Castle Windsor jest open - sourcowym projektem, jednym z pierwszych .NET-owych kontenerów IoC.W celu dodania go do projektu w Visual Studio korzystamy z NuGeta.


Podstawową przewagą nad Unity jest możliwość stworzenia własnych instalatorów - obiektów implementujących interfejs IWindsorInstaller. W instalatorze takim możemy skonfigurować część zależności. Podczas tworzenia kontenera mamy możliwość dodania wielu instalatorów.


public class AudiA4Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<AudiA4>().LifeStyle.Transient);
        container.Register(Component.For<IEngine>()
            .ImplementedBy<DieselEngine>().LifeStyle.Transient);
    }
}

Różnice w stosunku do Unity są dwie: musimy rejestrować typy o które prosimy bezpośrednio (nie przez interfejs), domyślny cykl życia obiektu to Singleton, dlatego konieczne jest ustawienie Transient - tworzenie nowej instancji przy każdym Resolve.

using (var windsorContainer = new WindsorContainer())
{
    windsorContainer.Install(new AudiA4Installer());
    var car2 = windsorContainer.Resolve<AudiA4>();
    car2.Run();
}

Castle Windsor wstrzykuje zarówno przez konstruktor jak i przez setter, tak więc klasa wyższego poziomu może być skonstruowana na dwa sposoby.