2010-02-23 8 views
5

J'ai la méthode suivante qui prend dans un objet de détails, le valide, le convertit en une demande et le met en file d'attente. Tout va bien à part la demande de validation avec laquelle j'ai des problèmes. Fondamentalement, il existe différentes logiques de validation pour chaque objet de détails différents. Je sais par la contrainte générique que l'objet détails doit avoir une classe de base de BaseDetails et du vrai paramètre générique je connais le type dérivé exact, mais je ne sais pas comment les utiliser pour écrire ma classe de validateur afin qu'il gère tous les types de détails :Question de polymorphisme débutant en utilisant des génériques

private void Enqueue<TDetails, TRequest>(TDetails details) 
    where TDetails: BaseDetails where TRequest: BaseRequest 
{ 
    bool isValid = _validator.Validate(details); 

    if (isValid) 
    { 
    TRequest request = ObjectMapper 
     .CreateMappedMessage<TDetails, TRequest>(details); 

    _queue.Enqueue(request); 
    } 
} 
+0

Avez-vous besoin d'une validation différente pour chaque implémentation de TDetails? –

+0

oui, certains sont communs, mais il y a différents bits supplémentaires pour chaque TDetails. –

Répondre

0

Je pense que vous devez créer une classe de validation pour chaque implémentation de TDetails qui sait comment valider cette implémentation particulière, puis avoir une fabrique pour produire le bon validateur pour une implémentation TDetails donnée et avoir votre classe _validator pour la classe correcte faire le travail de l'usine et amener la classe à faire la validation.

De toute évidence, vous pourriez avoir une partie de la validation commune dans une classe de base.

Vous pourriez être mieux d'avoir la validation sur l'objet lui-même si, plutôt que de créer un validateur pour chaque mise en œuvre de TDetails ...

+0

Re: l'usine - comment cela serait-il défini?Chaque validateur aurait une signature de méthode différente de celle qu'il prendrait dans un type différent, ou les déclarerais-je tous prendre dans la classe de base, puis passer au type dérivé dans chaque méthode de validation? –

+0

l'usine aurait une méthode 'IDetailsValidator GetValidator (TDetails)' et ferait alors un 'switch (typeof (TDetails))' et ensuite pour chaque cas retourner une implémentation de cette interface. cette interface aurait une méthode 'bool IsValid (TDetails)'. Chaque implémentation est convertie au type correct dans la méthode et effectue la validation. –

+0

vous ne pouvez pas échapper à la construction du grand switch (ou si c'est le cas), alors c'est une bonne idée de l'avoir dans un seul endroit (la classe factory) où vous pouvez ajouter de nouveaux validateurs au fur et à mesure écrit, plutôt que d'avoir à faire le contrôle à plusieurs endroits dans votre code. –

2

cela signifie simplement qu'il doit y avoir une hiérarchie de validateurs correspondante, chacun attaché à son propre objet TDetails. Puisque TDetails est toujours BaseDetails, vous devez spécifier manuellement la classe enfant que vous supportez et l'exécution en chaîne à un validateur imbriqué.

1

Pour moi, il semble que la logique de validation doit être jointe aux détails eux-mêmes des objets (si possible , bien sûr). Vous pouvez ensuite marquer l'abstraite de la classe de base et remplacer la méthode Validate pour des classes de détails spécifiques si nécessaire.

D'un autre côté, la «composition sur l'héritage» est à la mode pour le moment.

+0

Ce serait plus facile mais TDetails sont des contrats de données WCF et je ne suis pas autorisé à les toucher! –

+0

alors il semble que vous êtes coincé avec un validateur par TDetails. Espérons juste que vous avez le contrôle des implémentations de TDetails ... –

+0

@Stacey Alors j'utiliserais le conteneur d'injection de dépendances pour passer dans le validateur nécessaire (base ou détails dérivés spécifiques à la classe). De même que dans le modèle Repository largement accepté. –

1

Je sais de la contrainte générique que les détails objet doit avoir une classe de base de BaseDetails

Ceci est connu dans le processus de compilation en code octet (je veux dire Visual Studio sait)

et du paramètre générique réel Je sais que le type dérivé exacte

Mais ceci est connu que AFTE r Compilation JIT (Visual Studio ne sait rien à ce sujet). C'est comme une liaison tardive. Donc, si vous voulez écrire une classe de validateur avec plusieurs méthodes avec différents types d'arguments, vous ne pouvez pas faire cela, car le compilateur Visual Studio ne savait pas (au moment de la compilation) quelle méthode sera appelée. Je crois qu'il n'y a aucun moyen d'ignorer l'écriture de la logique switch (typeof (TDetails)), où le validateur doit être sélectionné par TDetails. Donc, vous devez écrire une sorte d'usine, comme Sam Holder a écrit ci-dessus.

PS: Désolé pour mon anglais. J'utilise aussi stackoverflow pour étudier l'écriture en anglais :)