Una libreria che ho utilizzato più volte, ma che è secondo me misconosciuta è ANTLR StringTemplate. E’ parte di un progetto molto più grande ed importante, ovvero il generatore di linguaggi ANTLR, ma qui ci interessa la libreria di templating.
bene: che cosa è ? E’ un template engine, ovvero un componente che, data qualche forma di metadata mi produce un documento di testo il cui contenuto è in qualche modo pilotato dal metadata. Semplice? Forse un esempio è meglio:
Supponiamo di avere un oggetto .NET rappresentante una carrello della spesa di un sito web. Questo rappresenta il nostro metadata. Ora supponiamo che vogliamo scrivere una mail riassuntiva, rappresentante il contenuto del carrello. Ovviamente dovrebbe essere facile modifcare il corpo di questa mail, la sua formattazione, tramite una semplice configurazione. Vediamo come potrebbe essere l’oggetto carrello in questione:
1: public class Basket
2: { 3: public Basket ()
4: { 5: BasketItems = new List<BasketItem>();
6: }
7: public string UserName { get; set; } 8: public string UserSurname { get; set; } 9: public string UserEmail { get; set; } 10: public IList<BasketItem> BasketItems { get; set; } 11: }
12:
13: public class BasketItem
14: { 15: public string Code { get; set; } 16: public string Description { get; set; } 17: public int Count { get; set; } 18: public decimal UnitPrice { get; set; } 19: public decimal Price { get { return UnitPrice * Count; } } 20: }
Bene, ora scriviamo il template della mail, nel linguaggio di StringTemplate:
1: Dear Mr $Basket.UserName$,$Basket.UserSurname$
2:
3: Your order contains:
4:
5: Item # Description Qty Unit Cost Total Cost
6: $Basket.BasketItems:
7: { 8: $it.Code$ $it.Description$ $it.Count$ $it.UnitPrice$ $it.Price$ }
9: $
10:
11: ______________________________
12: Thanks for ordering @ ACME.ORG
Da notare, se siete abituati ad altri template engine ( ASP è uno di questi, ma anche T4 ) noterete che questi quando lavorano con collezioni vi fanno scrivere qualcosa come <% for….. %>, facendovi fare il template in modo procedurale. StringTemplate usa invece un approccio dichiarativo $collection: {}$ tra le graffe va il template da ripeter per ogni item della collection. l’elemento corrente è rappresentato da $it$.
Ora bisogna procurere i binari del porting c# di StringTemplate. Mettete come reference nel vostro progetto le dll StringTemplate, ma ricordatevi che per il deploy servono tutte e tre le dll! Fatto questo, per processare il template basta scrivere:
1: public void TryTemplate()
2: { 3: using( var st = new StreamReader("mailtemplate.txt") ) 4: { 5: StringTemplate processor = new StringTemplate(st.ReadToEnd());
6: //GetBasket ritorna un basket di esempio
7: processor.SetAttribute("Basket", GetBasket()); 8: //ToString processa il template con i dati...
9: Console.WriteLine(processor.ToString());
10: }
11: }
Per ottenere l’output seguente:
1: Dear Mr Will,Coyote
2:
3: Your order contains:
4:
5: Item # Description Qty Unit Cost Total Cost
6:
7: 1 T.N.T Stick 200 0,45 90,00
8: 2 Chain Gun 1 1450 1450
9: 3 Rockets 60 200 12000
10:
11: ______________________________
12: Thanks for ordering @ ACME.ORG
Semplice, e molto efficace. Questo è un esempio base, collection e parametri a me sono sempre bastati, ma la libreria in se è molto più potente: basta leggersi la documentazione. So benissimo che a qualcuno potrebbe venire voglia, di fronte ad una simile problematica, di scriversi una propria versione, ma… okkio, questa è una delle classiche cose semplici che vi portano via, a farla male, una giornata, ma a farla bene… beh, prendete quella già fatta perchè:
- è collaudata - è usata come back-end di ANTLR, un genaratore di compilatori di successo-
- è potente – gestisce collection, sostituzioni, inclusioni, join etc etc
- è open source, ed è in C#.