26 Stimmen

Wie kann ich eine generische Containerklasse schreiben, die eine bestimmte Schnittstelle in C# implementiert?

Kontext: .NET 3.5, VS2008. Ich bin mir nicht sicher über den Titel dieser Frage, so fühlen sich frei, über den Titel zu kommentieren, auch :-)

Hier ist das Szenario: Ich habe mehrere Klassen, sagen wir Foo und Bar, alle von ihnen implementieren die folgende Schnittstelle:

public interface IStartable
{
    void Start();
    void Stop();
}

Und nun möchte ich eine Containerklasse haben, die in ihrem Konstruktor ein IEnumerable<IStartable> als Argument bekommt. Diese Klasse wiederum soll auch die Schnittstelle IStartable implementieren:

public class StartableGroup : IStartable // this is the container class
{
    private readonly IEnumerable<IStartable> startables;

    public StartableGroup(IEnumerable<IStartable> startables)
    {
        this.startables = startables;
    }

    public void Start()
    {
        foreach (var startable in startables)
        {
            startable.Start();
        }
    }

    public void Stop()
    {
        foreach (var startable in startables)
        {
            startable.Stop();
        }
    }
}

Meine Frage ist also: Wie kann ich es tun, ohne den Code manuell zu schreiben und ohne Codegenerierung? Mit anderen Worten, ich hätte gerne so etwas wie das Folgende.

var arr = new IStartable[] { new Foo(), new Bar("wow") };
var mygroup = GroupGenerator<IStartable>.Create(arr);
mygroup.Start(); // --> calls Foo's Start and Bar's Start

Sachzwänge:

  • Keine Codegenerierung (d. h. kein echter Textcode zur Kompilierzeit)
  • Die Schnittstelle hat nur ungültige Methoden, mit oder ohne Argumente

Motivation:

  • Ich habe eine ziemlich große Anwendung mit einer Vielzahl von Plugins mit verschiedenen Schnittstellen. Das manuelle Schreiben einer "Gruppencontainer"-Klasse für jede Schnittstelle "überlastet" das Projekt mit Klassen
  • Manuelles Schreiben des Codes ist fehleranfällig
  • Jede Ergänzung oder Signaturaktualisierung der IStartable-Schnittstelle führt zu (manuellen) Änderungen in der Klasse "Gruppencontainer".
  • Lernen

Ich verstehe, dass ich hier Reflexion verwenden muss, aber ich würde lieber ein robustes Framework verwenden (wie Castle's DynamicProxy o RunSharp ), um die Verkabelung für mich zu erledigen.

Haben Sie eine Idee?

0voto

TcKs Punkte 24671

Sie können die Klasse "List" und ihre Methode "ForEach" verwenden.

var startables = new List<IStartable>( array_of_startables );
startables.ForEach( t => t.Start(); }

0voto

Robert Venables Punkte 5903

Wenn ich richtig verstehe, fragen Sie nach einer Implementierung des "GroupGenerator".

Ohne wirkliche Erfahrung mit CastleProxy wäre meine Empfehlung, GetMethods() zu verwenden, um die anfänglichen Methoden zu erhalten, die in der Schnittstelle aufgelistet sind, und dann einen neuen Typ mit Reflection.Emit mit den neuen Methoden zu erstellen, die die Objekte aufzählen und jede entsprechende Methode aufrufen. Die Leistung sollte nicht allzu schlecht sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X