Se vado avanti così potrei diventare PostSharp addicted… già sono compiler addicted conclamato, sono sulla buona strada per diventare Unit Testing addicted e dopo aver provato la compile time validation di PostSharp posso asserire che si sta chiudendo il cerchio.
Un paio di giorni fa abbiamo visto come usare PostSharp per validare a runtime i parametri di un metodo (per inciso funziona anche con i costruttori) facendo semplicemente una cosa del genere:
class MyTestClass
{
public void Foo( [NotNull]String arg )
{
Console.WriteLine( "Foo( String ): " + arg );
}
}
e producendo a runtime una ArgumentNullException se chiamiamo Foo() passando un valore null. Adesso immaginiamo di scrivere una cosa del genere:
class MyTestClass
{
public void Foo( [NotNull, Int32RangeValidator( CompareLogic = CompareLogicOperator.Greater, ReferenceValue = 0) ]Int32 arg )
{
Console.WriteLine( "Foo( Int32 ): " + arg );
}
}
abbiamo un overload di Foo() che prende un intero e vogliamo che questo sia maggiore di 0 ma erroneamente, perchè Int32 è un value type, vogliamo anche che non sia null… compiliamo e:
Lasciatemi dire: semplicemente fantastico!
Il tutto è stato di una semplicità disarmante:
[Serializable]
public class ArgumentValidatorAspect : OnMethodBoundaryAspect
{
public override bool CompileTimeValidate( MethodBase method )
{
Boolean returnValue = true;
method.GetParameters()
.Where( pi => pi.IsAttributeDefined<NotNullAttribute>() )
.ForEach( pi =>
{
if( pi.ParameterType.IsValueType )
{
Message error = new Message( SeverityType.Error,
"RV0001",
"Cannot apply NotNullAttribute to a ValueType.",
method.Name );
MessageSource.MessageSink.Write( error );
returnValue = false;
}
} );
return returnValue;
}
}
PostSharp ha un motore di validazione che viene invocato a compile time e che ci permette di controllare, parzialmente, il processo di build eventualmente interrompendolo se non sono soddisfatti determinati requisiti, come nel nostro caso.
Questo apre a scenari notevoli, dimentichiamoci per un momento di tutto quello che PostSharp può fare a runtime e soffermiamoci solo sulla fase a compile time: la manna del programmatore sono gli errori del compilatore avere la possibilità di controllare il processo di build anche attraverso attributi custom/aspect è semplicemente potentissimo.
.m