2010-11-27 11 views
4

Ich denke, der Titel sagt nicht viel, also hier ist die Erklärung.C# generischer Typ Argument aus der Kindklasse, möglich?

Ich habe eine Elternklasse, die ich eine Ereignisaktion halten soll, wobei T ist der Typ von was auch immer Kindklasse erbt es.

z.B. so etwas wie diese:

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. 
    } 
} 

Die Frage ist also, ist die oben möglich ist, und was würde ich für T in der übergeordneten Klasse?

Beachten Sie, dass ich kein generisches Argument für meine Elternklasse haben möchte, da das wirklich dumm aussehen würde und somit die Lesbarkeit behindern würde.

class UserRecord : ActiveRecord<UserRecord> 

Ich arbeite an einer Erbschaft basierte ORM, falls Sie sich fragen, was es ist. Das NewItem-Ereignis wird immer dann ausgelöst, wenn das ORM Daten in die Datenbank einfügt.

Edit: Versuchen, ein bisschen besser zu klären, mit der richtigen Benennung der Klassen.

Die ActiveRecord-Klasse befindet sich in einer separaten Assembly, und die UserRecord befindet sich in einem Webprojekt, an dem ich gerade arbeite. (Hinweis: Ich bin der Entwickler beider Teile, es sind jedoch zwei separate Projekte.)

Ich möchte Ereignisse auslösen, nachdem ich eine Zeile erfolgreich eingefügt, eine Zeile gelöscht und so weiter. Die Ereignisse sollten den fraglichen Datensatz als Argument für den Ereignishandler übergeben, daher müssen Aktionen ausgeführt werden.

Allerdings, wie ich diese Ereignisse in der Basisklasse (ActiveRecord) deklariere, brauche ich eine Möglichkeit, den CHILD-Typ an die Ereignisbehandlungsroutinen zu übergeben, um ein stark typisiertes Objekt zu erhalten.

ich könnte natürlich Aktion gehen und dann eine Typumwandlung in meiner Implementierung tun, aber das wäre wirklich nicht sehr schön :-(

Hoffnung, dass die Frage ein wenig aufräumt, sonst fragen Sie bitte: -)

Edit 2: Ich wollte nur wissen lassen, Reflexion, dynamische Methoden oder etwas ähnliches ist eine Option, wenn das helfen würde. Allerdings bezweifle ich, es für dieses spezielle Szenario :-(

+4

Etwas riecht hier falsch - ist das Kind das Element Ihres Modells und Eltern ist der Behälter? Oder ist es anders herum? Kannst du etwas mehr erklären? –

Antwort

0

Eigentlich denke ich, ich habe gerade einen viel besseren Ansatz:

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

class UserRecord : ActiveRecord 
{ 

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

Dies ist für mich viel mehr sauber scheint, so werde ich stattdessen verwenden.

6

würde ich nicht wirklich empfehlen, aber man konnte eine C# Version der curiously recurring template pattern verwenden:

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 
    } 
} 

In der Praxis wird dies ziemlich schwierig sein, . verwenden vernünftig, es muss eine bessere Lösung für die Gesamtgestaltung sein, in aller Ehrlichkeit

+0

Ich stimme zu, dass es schwierig sein würde, vernünftig zu verwenden, und da andere Leute am Ende die Bibliothek benutzen, ist das meine erste Priorität. Danke für den Vorschlag. – Steffen

+0

Dies scheint der beste Weg zu sein. – Steffen

0

Versuchen Sie folgendes:

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

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

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

Wenn Sie nichtmachen 210 zu abstract, können Sie eine abstrakte Übergangsklasse zwischen Parent und Child hinzufügen.

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

Während das funktionierte, hoffte ich wirklich auf eine Möglichkeit, das generische Argument in der Child-Klasse zu vermeiden. – Steffen

Verwandte Themen