Supponiamo di avere un Assembly che ci mette a disposizione il servizio di invio E-mail:
public class EmailSender
{
public virtual void Send(string from, string to, string message)
{
Console.WriteLine("Email from:{0}\nTo:{1}\nMessage:{2}", from, to, message);
}
}
Ovviamente l'implementazione nel mondo reale sarà un pò più complessa, ma per il nostro scopo è più che sufficiente.
Il nostro codice ora è in produzione e siamo tutti felici. Ad un certo punto il responsabile della sicurezza che per definizione non ha a cuore noi developers, decide che tutto ciò che viene mandato via mail deve essere loggato.
Orrore oltraggio! devo modificare il mio codice introducendo come dipendenza un engine di logging.
Ebbene con l'Aspect Oriented Programming (spiegata più in dettaglio nel wiki di UGIdotNET in questo articolo) non è necessario. Possiamo aggiungere la funzionalità di logging senza modificare il codice originale!
Vediamo come:
Per prima cosa ci serve un file di configurazione:
aspect Logger for EmailSender
pointcut method|property(*)
advice(LoggerInterceptor)
end
end
Per ora lo mettiamo in una stringa, ma in una situazione reale è meglio inserirlo ad esempio nell'App.Config.
Modifichiamo a questo punto il main con le seguenti istruzioni:
static void Main(string[] args)
{
string content =
"aspect Logger for EmailSender\n" +
" pointcut method|property(*)\n" +
" advice(LoggerInterceptor)\n" +
" end\n" +
"end";
AspectEngineBuilder builder = new AspectLanguageEngineBuilder(content);
AspectEngine engine = builder.Build();
EmailSender sender = (EmailSender) engine.WrapClass(typeof(EmailSender));
sender.Send("pippo@msn.it", "pluto@msn.it", "ciao");
Console.ReadLine();
}
A questo punto implementiamo il nostro logger:
public class LoggerInterceptor : IMethodInterceptor
{
public LoggerInterceptor() {}
public object Invoke(IMethodInvocation invocation)
{
EmailSender sender = (EmailSender)invocation.This;
Console.WriteLine("Logger****");
return invocation.Proceed();
}
}
Se lanciamo il programma otteniamo il seguente output:
Logger****
Email from:pippo@msn.it
To:pluto@msn.it
Message:ciao
Alcune note: la classe LoggerInterceptor è specificata nella configurazione come advice, i metodi intercettati devono essere virtual.
Il codice di esempio utilizza AspectSharp il quale fa parte del Castle Project.