2010-11-27 5 views
4

Je suppose que le titre ne dit pas vraiment beaucoup, alors voici l'explication.Argument de type générique C# de la classe enfant, possible?

J'ai une classe parente, que je veux contenir un événement Action, où T est le type de n'importe quelle classe enfant qui l'hérite.

par exemple. quelque chose comme ceci:

abstract class ActiveRecord 
{ 
    protected event Action<T> NewItem; 
} 

class UserRecord : ActiveRecord 
{ 
    public UserRecord() 
    { 
    NewItem += OnNewItem; // NewItem would in this case be Action<UserRecord> 
    } 

    private void OnNewItem(UserRecord obj) 
    { 
    // Flush cache of all users, since there's a new user in the DB. 
    } 
} 

La question est, est possible ci-dessus, et qu'est-ce que j'utiliser pour T dans la classe des parents?

Notez que je ne veux pas d'argument générique pour ma classe parente, car cela aurait vraiment l'air stupide, et donc entraver la lisibilité. Je travaille sur un ORM basé sur l'héritage, au cas où vous vous demanderiez à quoi il sert. L'événement NewItem est déclenché chaque fois que l'ORM insère des données dans la base de données.

Editer: Essayer de clarifier un peu mieux, avec un nom correct des classes.

La classe ActiveRecord réside dans un assembly séparé et UserRecord réside dans un projet Web sur lequel je travaille. (Note: Je suis le développeur des deux parties, mais il s'agit de deux projets distincts)

Je veux être en mesure d'élever des événements en insérant avec succès une ligne, en supprimant une ligne, et ainsi de suite. Les événements doivent transmettre l'enregistrement en question en tant qu'argument au gestionnaire d'événements, d'où la nécessité d'une action.

Cependant, comme je déclare ces événements dans la classe de base (ActiveRecord), j'ai besoin d'un moyen de passer le type CHILD aux gestionnaires d'événements, afin d'obtenir un objet fortement typé.

Je pouvais bien sûr aller Action, puis faire un transtypage dans ma mise en œuvre, mais ce ne serait vraiment pas très agréable :-(

Hope this efface un peu la question, sinon s'il vous plaît demander: -)

Édition 2: Je voulais juste vous faire savoir que la réflexion, les méthodes dynamiques ou quelque chose de similaire est une option, si cela pouvait aider. Cependant, je doute pour ce scénario particulier :-(

+4

Quelque chose sent mauvais ici - l'enfant est-il l'élément de votre modèle et le parent est le conteneur? Ou c'est un autre moyen? Pouvez-vous expliquer un peu plus? –

Répondre

0

En fait, je pense que je viens de trouver une approche beaucoup mieux:

abstract class ActiveRecord 
{ 
    protected virtual void OnNewItem() {} 
} 

class UserRecord : ActiveRecord 
{ 

    protected override void OnNewItem() 
    { 
    // Still got the UserRecord object, now it's just "this" 
    } 
} 

Cela me semble beaucoup plus propre, donc je vais utiliser ce lieu.

6

Je ne recommanderais pas vraiment, mais vous pouvez utiliser une version C# du curiously recurring template pattern:

class Parent<T> where T : Parent<T> 
{ 
    protected event Action<T> NewItem; 
} 


class Child : Parent<Child> 
{ 
    public Child() 
    { 
     NewItem += OnNewItem; 
    } 

    private void OnNewItem(Child obj) 
    { 
     // Do something 
    } 
} 

Dans la pratique, ce sera assez difficile à . utiliser judicieusement, il doit y avoir une meilleure solution pour la conception d'ensemble, en toute honnêteté

+0

Je suis d'accord que ce serait difficile à utiliser raisonnablement, et puisque d'autres personnes pourraient finir par utiliser la bibliothèque, c'est ma première priorité. Merci pour la suggestion cependant. – Steffen

+0

Cela semble être le meilleur moyen. – Steffen

0

Essayez ceci:

abstract class Parent<T> 
{ 
    public event Action<T> NewItem; 
} 

class Child : Parent<Child> 
{ 
    public Child() 
    { 
     NewItem += OnNewItem; 
    } 

    private void OnNewItem(Child obj) 
    { 
     // Do something 
    } 
} 

Si vous ne pouvez pas faire Parent pour être abstract, vous pouvez ajouter une classe de transition abstraite entre Parent et Child.

class Parent<T> 
{  
    public event Action<T> NewItem; 
} 

abstract class Transition<T> : Parent<T> { } 

class Child : Transition<Child> 
{ 
    public Child() 
    { 
     NewItem += OnNewItem; 
    } 
    private void OnNewItem(Child obj) 
    { 
     // Do something 
    } 
} 
+0

Alors que cela fonctionne, j'espérais vraiment un moyen d'éviter l'argument générique sur la classe enfant. – Steffen

Questions connexes