Premessa
Nel mio caso io ho lavorato sul web.config, ma dato che non ho fatto  nulla di tracendentale e ho utilizzato solo classi del framework e nulla di  personalizzato, presumo che se il file di configurazione sia quello di un  applicativo, non dovrebbero esserci problemi. 
Ricordo che una soluzione per antonomasia non esiste, questo è chiaro. Sulle prima, infatti, non ero nemmeno sicuro che questa fosse quella che faceva al caso mio, e tra l'altro avevo anche dei problemi nel  farla funzionare, sicchè mi venne suggerito di usare un semplice schema XML/XSD, che se sulle prime poteva sembrare efficace, immaginando meglio lo scenario finale, risultava poco "sicuro" per via del fatto che chiunque avesse avuto accesso al sorgente del sito avrebbe potuto variare il contenuto del valore da validare. Quindi sono ritornato sui miei passi e ho iniziato a capirci qualcosa dei Validator.
Al lavoro dunque!
La necessità
Poter controllare cosa accidenti scrive l'utente in un file  di configurazione.
Soluzione
Sulle prime quando ho cercato di capire come potessi fare a  validare, la prima ricerca che ho fatto è stata proprio "Custom Validator" e -  benchè mi pare di capire che questo sia il nome di quello di cui sto parlando -,  tutti i risultati che venivano fuori (Msdn, google, ecc.) erano riferiti a  custom validator che però si associavano esclusivamente a controlli sulle  webform. Il che non era esattamente quello che volevo.
Mi sono guardato un attimo intorno, ed in particolare sul fatto di cosa  una custom configSections (per crearla bisogna ereditare  da ConfigurationSection) e i suoi elementi (creabili da  ConfigurationElement) e qui erano saltati fuori StringValidator e compagni.
Erano esattamente quello che  mi serviva. Allora, come da ogni buon programmatore (??) guardo da che classe  ereditano ... e nel caso dello StringValidator, da StringValidatorAttribute che come unica proprietà  da implementare richiede la ValidatorInstance, una proprietà di sola  lettura che restituisce un oggetto, la vostra classe, di tipo ConfigurationValidatorBase che si occuperà di  fare il lavoro "sporco" e di validare il contenuto dell'attributo del file di  configurazione, richiamando dapprima il metodo CanValidate per verificare  che il tipo di dati datogli in pasto sia validabile secondo la nostra classe e  poi il rispettivo Validate per sapere se il valore è o meno  valido.
Reperite queste informazioni, il gioco è stato abbastanza (??)  semplice. 
Ma vediamo qualche linea di codice:
    public sealed class NomeValidatorAttribute 
                       : ConfigurationValidatorAttribute
    {
        NomeValidator istance;
        public NomeValidatorAttribute()
        {
        }
        public override ConfigurationValidatorBase
          ValidatorInstance 
        { 
            get
            {
                if (istance == null)
                    istance = new NomeValidator();
                    
                return istance;
            }
        }
    }
Con questa classe - non ereditabile (non sia mai qualcuno tocchi il  mio codice) - qui sopra non faccio altro che definire un oggetto di tipo  attributo (perchè eredita da ConfigurationBaseAttribute che a sua volta eredita  da Attribute) che chiamo - guarda caso per ricordarmi - con il nome del mio  attributo presente nel file di configurazione con l'aggiunta del suffisso  Validator tanto per rimanere in stile Microsoft (La parola Attribute che segue  Validator sebbene non strettamente indispensabile e caldamente ignorata dall'IDE  ce l'ho aggiunta per la stessa identica ragione - rimanere con una classe stile  Microsoft).
All'interno dichiaro una variabile globale di tipo Validatore (che ancora non  ho mostrato), il costruttore di default, e l'impementazione della proprietà  ValidatorInstance.
Non mi soffermo di più sul fatto che all'interno della classe si potevano  creare dei NamedParameter con i quali poter accettare dei  valori opzionali in ingresso, o ulteriori costruttori firmati. Ma per lasciare  le cose semplici, supponiamo che a noi non interessano parametri.
A questo punto, dobbiamo scrivere la nostra classe che si occupa di validare  il contenuto dell'attributo. Ecco qua:
    public class ContentTypeValidator 
             : ConfigurationValidatorBase
    {
        String[] ct = new String[] {"Andrea", "Giuseppe"};
        public ContentTypeValidator()
        {
        }
    
        public override bool CanValidate(Type type)
        {
            return type == typeof(string);
        }
    
        public override void Validate(object value)
        {
             if (Array.IndexOf(ct, value) == -1)
                throw new ConfigurationErrorsException(
         "The name value supplied isn't allowed");
        }
    }
 
Ok, forse non sarà il massimo dell'eleganza dichiarare quell'array lassu,  secco con due valori e francamente in un caso dove realmente dovrei validare il  nome scegliendolo da una lista di possibili valori, sinceramente ho qualche  difficoltà anche io a capire come andarli a leggere da un elenco più nutrito che  non mi sia scritto prima a mano. Ma questo è pur sempre un esempio.
Questa classe, come dicevo prima, controlla il contenuto dapprima verificando  che il tipo in ingresso sia valido e poi validandolo, e in caso negativo si  preoccupa di sollevare un'eccezione al compilatore con relativo messaggio che  aiuti a capire cosa è successo.
Come uso il tutto? Intanto prendendo le due classi e mettendole nel codice,  poi, sempre premesso che stiate lavorando su di un configuration element, non  dovrete far altro che andare al di sotto della vostro elemento,  
mettere una parentesi quadra per aggiungere un attributo ed ecco che magicamente compare nella nostra lista il nostro validatore.

Et voilà, il gioco è fatto.