AOP - PostSharp vs Windsor

by DotNetNerd 27. February 2009 20:56

På mit seneste projekt har jeg kigget nærmere på at lave AOP ved hjælp af henholdsvis PostSharp og Castle Windsors IInterceptor. De to fremgangsmåder har hver sine fordele og ulemper, men begge har også nogle shortcomings.

Castle Windsors bud på AOP virker ved at man implementerer en IInterceptor, hvilket kræver at man skriver en Intercept metode der tager et IInvocation objekt som argument, hvorpå man kan kalde Proceed der hvor metoden skal indkapsles. Interceptoren registreres så for en klasse, hvilket bevirker at alle metoder på klassen indkapsles.
En typisk implementation ser sådan her ud:

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // Entry logic
        invocation.Proceed();
        // Exit logic
    }
}

Postsharp, som et et lille framework til at lave AOP i .NET, virker ved at man implementerer en attribut der extender en af frameworkets aspects - eksempelvis OnExceptionAspect, OnMethodInvocationAspect eller OnMethodBoundaryAspect. I og med det er en attribut man implementerer påføres denne blot de metoder man ønsker skal indkapsles.
To helt typiske eksempler kunne være:

public class LoggingAttribute : OnMethodBoundaryAspect   
{       
    public override void OnEntry(MethodExecutionEventArgs eventArgs) { //Entry logic }        
    public override void OnExit(MethodExecutionEventArgs eventArgs) { //Exit logic }   
}

public class LoggingAttribute : OnMethodInvocationAspect   
{
    public override void OnInvocation(MethodInvocationEventArgs eventArgs)       
    {           
        //Entry logic
        eventArgs.Delegate.DynamicInvoke(eventArgs.GetArguments());           
        //Exit logic
    }
}

PostSharp er dermed mere finkornet i forhold til at man kan vælge hvilke metoder der indkapsles, og ved at man implementerer et passende aspect - omvendt er det i scenarier hvor alle metoder skal påvirkes og det virker dejligt ligetil med IInterceptor når amn alligevel bruger castle windsor.

Et punkt hvor castle windsor udmærker sig er at argumenter kan tilgås via IInvocation objektet ud fra navn frem for at de udelukkende kan tilgås via index - som desværre det eneste PostSharp tilbyder. Det er efter min mening en rimelig stor mangel i PostSharp, da det betyder at man ikke kan gøre koden robust i forhold til scenarier hvor et parameters navn er mere pålidelige end index - noget der er typisk i f.eks MVC løsninger.

I et scenarie jeg sad med fornylig var det actions på en controller, der bliver kaldt via reflection af MVC frameworket, som jeg ønskede at indkapsle, således at jeg via AOP kunne styre authorization. Her viste sig nogle uhensigtsmæssighed i begge måder at lave AOP. Det var for det første mere besværligt at finde ud af hvilken action der var kaldt, på grund af begge frameworks egentlig indkapsler de metoder der kalder min action via reflection. Derudover var det svært at lave koden solid i forhold til ændringer i navngivning af controllers og actions - da mine regler for authorization nødvendigvis må bindes op  på hvilken controller/action de gælder for.

Løsningen blev at lave unittests der via reflection verificerer at de authorization regler der er sat op rent faktisk matcher en controller og action. For at sikre at man ikke glemmer at sætte regler op for en given action indførte jeg desuden "secure by default" ved at nægte adgang til actions der ikke er konfigureret authorization for.

 

Tags:

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List