Un wrapper è il modo giusto per andare qui - vuoi davvero che la parte dell'interfaccia utente del livello dell'interfaccia utente rifletta solo ciò che viene dato e non sia responsabile di qualcosa di molto tecnico rispetto ai contenuti filtranti. Vorrei correre con la prima opzione che stai guardando e creare una sottoclasse specifica per il livello dell'interfaccia utente per gestire questa attività.
Il costo reale dal punto di vista del codice di scrittura non consiste nell'aggiornare il EscapedBook
ogni volta che la classe sottostante cambia: le classi sottostanti cambiano e cambieranno molte cose lungo la linea logica. Sarebbe meglio avere la rappresentazione interna che parla a una singola classe piuttosto che parlare direttamente con una dozzina di cose diverse nell'applicazione front-end.
Questa classe specifica front-end potrebbe benissimo essere generata tramite un processo proxy o AOP - questa è davvero una decisione tattica a seconda di quale sia lo stack e di quali altre dipendenze hai. Potresti voler dire avere un proxy dedicato diretto piuttosto che una classe separata. Questa non è un'idea orribile in superficie, ma alla fine preferirei il concetto di classe dedeciso - è più flessibile separare i problemi alla fine.
Qui è meglio evitare la classe di utilità: si finirà con cose come ContentUtil.CleanPage(book.Pages[1])
su tutto il livello dell'interfaccia utente e questo farà male a risolvere quando si ripensano le cose. I globali sono cattivi, anche quando i globali sono funzioni di utilità stateless.
Una cosa che non vorrei buttare fuori è che venga generata nel livello aziendale - la generazione di contenuti con escape appropriati è un requisito aziendale verificabile dell'applicazione che preferisco testare con il livello aziendale anziché provare a scrivere test automatici del UI.