TL; DR:méthode Redéfinir type de retour en classe dérivée sans génériques
Est-il possible d'ajouter une méthode abstraite à une classe de base qui permet aux classes dérivées de passer outre le type de retour de la méthode, sans utilisation de génériques, et sans l'utilisation du mot-clé
new
?
Je travaille sur le développement de certains modèles personnalisés pour LLBLGen Pro. Dans le processus, je refuse de modifier les modèles par défaut proposés par LLBLGen Pro, de sorte que mon approche ne remplace pas les fichiers d'autres personnes s'ils choisissent d'implémenter mes modèles. Une tâche sur laquelle j'ai commencé à travailler (et qui a bien progressé vers) consiste à développer un modèle qui génère un DTO pour chaque entité. Dans ce sens, un objectif est de fournir à mes entités une méthode ToDTO()
. Dans l'intérêt de la programmation générique, j'ai décidé de définir cette méthode au sein d'une classe de base commune, et c'est là que mes problèmes commencent.
Gardez à l'esprit que le but de définir la méthode ToDTO()
dans la classe de base est parce que je suis à la recherche de créer un référentiel générique (avec une méthode Fetch()
, par exemple) que je voudrais avoir travailler sur le CommonEntityBase
, par opposition à une entité spécifique.
LLBLGen définit sa CommonEntityBase
classe comme ceci:
public abstract partial class CommonEntityBase : EntityBase2 {
// LLBLGen-generated code
}
Mon plan initial était d'ajouter ma méthode à une autre classe partielle comme ceci:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
Je pensais que les hérita Les classes seraient capables de définir le type de retour dans leurs méthodes comme un type dérivé du type de retour de la classe de base, comme ceci:
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
mais I was wrong.
Ma deuxième tentative a été de définir la classe en utilisant les génériques, comme tel:
public abstract partial class CommonEntityBase<T> : CommonEntityBase
where T : CommonDTOBase {
public abstract T ToDto();
}
assez simple. Tout ce que je dois faire est de faire hériter mes classes d'entités générées de cette nouvelle base d'entité. Juste une mise en garde. Comme je ne veux pas écraser les modèles de LLBLGen, je reviens à des classes partielles.
entités individuelles de LLBLGen ont cette définition:
public partial class PersonEntity : CommonEntityBase {
// LLBLGen-generated code
}
Et c'est là mon problème.Pour ma méthode de travail, je dois créer ma propre classe partielle avec cette définition:
public partial class PersonEntity : CommonEntityBase<PersonDTO> {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Bien sûr, cela est impossible, parce que, as I now know,
Toutes les les parties [d'une classe partielle] qui spécifient une classe de base doivent être d'accord, mais les parties qui omettent une classe de base héritent toujours du type de base.
La troisième chose que je vais essayer était primordial simplement la définition de la fonction de la classe de base avec le mot-clé new:
public abstract partial class CommonEntityBase {
public virtual CommonDTOBase ToDto(){ return null; }
}
public partial class PersonEntity : CommonEntityBase {
public new PersonDTO ToDto(){ return new PersonDTO(); }
}
Cependant, ce défaites le but de mon approche complètement, comme je vous voulez pouvoir accéder à la méthode ToDTO()
de PersonEntity
lorsqu'elle est lancée en tant que CommonEntityBase
. Avec cette approche, faire:
CommonEntityBase e = new PersonEntity();
var dto = e.ToDto();
entraînerait dto
étant nul, que je ne veux pas.
Je suis venu à travers variouslinks discuter de ma première approche, et pourquoi il ne fonctionne pas, et pointant généralement à mon approche générique en tant que solution dans le sens général. Cependant, dans ma situation, les génériques ne semblent pas fonctionner. Tout cela pour me demander si ce que j'essaie d'accomplir est possible ou non. Existe-t-il un moyen d'ajouter une méthode abstraite à une classe de base qui permet aux classes dérivées de remplacer le type de retour de la méthode, sans l'utilisation de génériques, et sans l'utilisation du mot-clé new
? Ou peut-être que j'aborde ce point du mauvais angle, et il y a une autre technique qui pourrait résoudre mes problèmes?
EDIT
est ici un cas d'utilisation pour ce que je voudrais accomplir avec les entités, en Porges's approche:
public class BaseRepository<D,E> where D : CommonDTOBase where E : CommonEntityBase,new
public D Get(Guid id){
var entity = new E();
entity.SetId(id);
// LLBLGen adapter method; populates the entity with results from the database
FetchEntity(entity);
// Fails, as entity.ToDto() returns CommonDTOBase, not derived type D
return entity.ToDto();
}
}
Vous semblez avoir quelques problèmes conceptuels avec les classes 'partial'. Il n'y a pas de magie en jeu; Je pense que la meilleure façon d'y penser est que le compilateur insère tout le code défini pour une classe partielle dans une définition de classe avant de compiler. – porges
Google "types de retour covariant". –