Surcharger les méthodes génériques
Lors de l'appel d'une méthode générique pour le stockage d'un objet, il y a parfois besoin de gérer un type spécifique différemment. Je sais que vous ne pouvez pas surcharge basée sur les contraintes, mais aucune autre alternative semble présenter ses propres problèmes.
public bool Save<T>(T entity) where T : class
{ ... some storage logic ... }
Ce que j'aimerais faire, c'est quelque chose comme ce qui suit:
public bool Save<SpecificClass>(T entity)
{ ... special logic ... }
Dans le passé, notre équipe a créé "one-off" méthodes pour l'enregistrement de ces classes comme suit:
public bool SaveSpecificClass(SpecificClass sc)
{ ... special logic ... }
Toutefois, si vous ne SAVEZ pas que la fonction existe, et vous essayez d'utiliser le générique (Enregistrer) ensuite, vous pouvez exécuter dans une foule de problèmes que le "one-off" était censé résoudre. Cela peut être aggravé si un nouveau développeur qui vient, voit le problème avec les génériques, et décide qu'il va fixer avec son propre d'une fonction d'arrêt.
Donc...
Quelles sont les options pour travailler autour de ce qui semble être question commune?
Que j'ai regardé, et utilisé UnitOfWork et maintenant ce qui semble être la seulement option qui en fait résout le problème, mais semble comme attaquant une mouche avec un marteau de forgeron.
source d'informationauteur Patrick Dench
Vous devez vous connecter pour publier un commentaire.
Que vous pouvez faire :
Par exemple:
Parce que la fonction et la surcharge de l'opérateur impliquant les génériques sont liés au moment de la compilation plutôt qu'au moment de l'exécution, si le code a deux méthodes:
alors le code qui tente de l'appeler
Save(Foo)
oùFoo
est une variable de certains type générique sera toujours appeler l'ancien surcharge, même lorsque le type générique qui arrive à êtreSomeClass
. Ma suggestion pour résoudre serait de définir une interface génériqueISaver<in T>
avec une non-méthode génériqueDoSave(T param)
. Avoir la classe qui fournit l'Save
méthode de mettre en œuvre toutes les interfaces génériques pour les types qu'il peut gérer. Alors l'objetSave<T>
méthode essayez de lancerthis
à unISaver<T>
. Si le sort réussit, l'utilisation de laISaver<T>
; sinon effectuer un générique enregistrer. À condition que le type de classe de la déclaration de la liste de toutes les interfaces appropriées pour les types il peut sauver, cette approche permettra d'expéditionSave
les appels aux méthodes appropriées.Bien bref C# ne permet pas de modèle de spécialisation, sauf par le biais de l'héritage comme ceci:
Au moins il ne prend pas en charge ce cours moment de la compilation. Cependant, vous pouvez utiliser le RTTI pour faire ce que vous essayez d'atteindre:
La
expression est assez pratique pour faire runtime type de contrôles. Il fonctionne de manière similaire au code suivant:
MODIFIER : Il est assez commun pour les types inconnus à utiliser le modèle suivant:
EDIT 2 : Comme les autres réponses suggèrent surcharge la méthode avec le
SpecializedClass
vous devez prendre soin de si vous travaillez avec le polymorphisme. Si vous utilisez des interfaces pour votre référentiel (qui est en fait une bonne manière de concevoir le modèle de référentiel) il y a des cas où la surcharge conduirait à des cas dans lesquels vous êtes à la mauvaise méthode de obtenir ce qu'on appelle, peu importe si vous êtes de passage à un objet deSpecializedClass
à l'interface:Cela fonctionne si vous appelez directement
FooRepository.Save
avec une instance deFoo
:Mais cela ne fonctionne pas si vous appelez de l'interface (par exemple, si vous utilisez des modèles pour mettre en œuvre la création de référentiel):
Utilisant le RTTI il n'y a qu'un
Save
méthode et vous serez amende.Pourquoi utiliser des noms différents pour votre méthode?
Voir la suivante: