Arriviamo con questo post alla parte più succulenta di Happy Sign. Nel mio ultimo post, ho descritto la differenza tra firme normali e firme dinamiche. Oggi vedremo come sia possibile che una firma dichiarata in questo modo:
L'ultimo post sul mio blog è: {0}
diventi una cosa simile a questa:
L'ultimo post sul mio blog è: Mediterranea Virtual: è o non è una community?
La firma dinamica è una firma come tutte le altre (eredita quindi da SignatureBase) e ne specializza il comportamento, aggiungendovi le seguenti proprietà:
- una stringa contenente il codice
- una StringCollection contenente eventuali assembly aggiuntivi necessari alla compilazione del codice
- un enum che esprime il linguaggio .NET in cui è scritta la classe (VB.NET o C#)
Il metodo GetSignatureText della classe DynamicSignature non fa altro che istanziare un oggetto compilatore (abstract class CodeDomProvider di .NET), aggiungere i riferimenti necessari e compilare il codice. Se non ci sono errori, ottiene un riferimento all'interfaccia IHappySignScript, di cui parleremo più avanti, assolutamente necessaria per fare tutto il resto.
Vediamo qualche riga di codice.
private static string InternalGetSignatureText(DynamicSignature DynamicSignature)
{
if (!DynamicSignature.References.Contains(hsCoreLocation))
DynamicSignature.References.Add(hsCoreLocation);
_results = Scripting.CompileScriptFromSource(
DynamicSignature.Code,
DynamicSignature.References,
DynamicSignature.Language);
IHappySignScript s = (IHappySignScript)Scripting.FindInterface
(_results.CompiledAssembly, "IHappySignScript");
object[] valuepar = new object[DynamicSignature.HowManyParametersInCode];
for (int i = 0; i < DynamicSignature.HowManyParametersInCode; i++)
valuepar[i] = s.GetValueParameter(i - 1);
return (string.Format(DynamicSignature.Text, valuepar));
}
Questo è un metodo dichiarato come private che è stato appositamente creato per isolare il più possibile le parti forse più complesse di Happy Sign. Il codice è stato opportunamente accorciato ed impaginato per essere pubblicato in questo post. L'unico parametro in input a questo metodo è un oggetto DynamicSignature, mentre il tipo di ritorno è una semplice string. Questo metodo demanda la compilazione vera e propria al metodo statico CompileScriptFromSource della classe Scripting, ed ottiene un riferimento ad un oggetto della classe CompilerResults, che ci permette in ultima analisi di fare due cose: 1) controllare se la compilazione è andata a buon fine oppure no e 2) ottenere un riferimento ad un tipo, nella fattispecie all'interfaccia IHappySignScript.
L'Interfaccia IHappySignScript
L'implementazione di questa interfaccia prevede la creazione di un solo metodo, GetValueParameter, definito come:
public interface IHappySignScript
{
string GetValueParameter(int WhichParameter);
}
Dopo aver compilato il codice associato alla firma, viene chiamato questo metodo n volte, dove n è il numero di parametri inseriti nel testo della firma. Ogni parametro - dicevamo l'altra volta - è identificato dal pattern {x}, dove x può valere 0, 1, 2, 3 e così via. L'ultima riga di codice non fa altro che sfruttare il metodo statico Format della classe string, formattando il testo della firma sostituendo ad ogni {x} il valore corrispondente ritornato dall'esecuzione del codice compilato.
Un piccolo esempio reale
All'inizio ho fatto vedere il testo di una firma il cui scopo è decorare le proprie e-mail aggiungendo il titolo dell'ultimo post inserito sul proprio blog. Il parametro {0} viene sostituito a run-time nel momento in cui facciamo drag'n'drop della firma. Lo script di Happy Sign è il seguente:
public class Script : HSCore.IHappySignScript
{
public string GetValueParameter(int WhichParameter)
{
XmlDocument doc = new XmlDocument();
doc.Load(@"http://blogs.ugidotnet.org/idamiani/Rss.aspx");
XmlNode nd = doc.DocumentElement.ChildNodes[0].ChildNodes[5].ChildNodes[1];
return(nd.InnerText);
}
}
Molto semplice, no? Questa è una normalissima classe (il nome Script è casuale, non ci sono vincoli su questo) che implementa l'interfaccia IHappySignScript. Questa classe deve implementare il metodo GetValueParameter, che in questo caso ritorna una stringa ottenuta analizzando tramite DOM il feed XML del proprio blog. In questo caso il parametro WhichParameter non viene utilizzato, perchè la firma contiene un parametro solo. Se avessimo una firma più complessa, potremmo ad esempio scrivere un costrutto switch nello script, oppure appoggiarci ad un assembly esterno che, oltre a migliorare la leggibilità del codice, permette di nascondere codice potenzialmente pericoloso.
Il prossimo post renderà pubblici alcune classi che ho già realizzato e che possono essere utilizzate in Happy Sign per decorare tutto quello che volete.