Questo è un fatto, comodo, da tempo:
readonly IEntityViewModelFactory viewModelFactory;

public PaymentMethodEditorViewModel( IEntityViewModelFactory viewModelFactory )
{
    Ensure.That( viewModelFactory ).Named( "viewModelFactory" ).IsNotNull();

    this.viewModelFactory = viewModelFactory;
}
se la validazione fallisce a runtime vi beccate un sana ArgumentNullException. Ci sono una notevole quantità di metodi e di extension methods che servono per validare gli scenari più disparati:
void MyMethod( String argument )
{
    Ensure.That( argument )
        .Named( "argument" )
        .WithMessage( "...ti sei dimenticato il parametro :-)" )
        .IsNotNullNorEmpty();
}
Fino a ieri aveva un solo difetto: era complessivamente complesso capire dove fosse realmente fallita la validazione perchè l’exception viene sollevata dalla libreria di validazione e non dal codice chiamante quindi l’unica possibilità era armarsi di pazienza e spulciare lo StackTrace… con l’inghippo che se il tutto è in un mondo multi-threading lo StackTrace è tutto tranne che developer friendly :-)
Una paio di giorni fa durante una ciaccolata con Marco De Sanctis salta fuori l’inghippo di cui sopra e stuzzicato dalla possbilità di risolverlo mi armo di curiosità e, grazie anche a uno scambio di mail con un paio di MVP d’oltreoceano (mirate a capire se c’era modo di ingannare il debugger), scopro che:
  • La proprietà StackTrace della classe Exception è virtual… :-)
  • c’è quindi la possibilità di manipolare a runtime lo StackTrace e rimuovere le informazioni che non servono…;
  • …ma questo probabilmente è poco bello oltre al fatto che comporterebbe una gerarchia custom di Exception;
perchè quindi non limitarsi ad utilizzare lo StackTrace per recuparare le informazioni necessarie a dettagliare meglio l’errore? facendo si che questo snippet:
static void Main( string[] args )
{
    try
    {
        Ensure.That( args )
            .Named( "args" )
            .WithMessage( "Missing console arguments." )
            .IsFalse( v => v.Length == 0 );
    }
    catch( ArgumentException e )
    {
        Console.WriteLine(e);
    }

    Console.Read();
}
produca questo:
image
Sempre perchè anche il developer vuole la sua parte :-)
.m