Frage

Ich habe ein 100 Klassen, die einige ähnliche Elemente und einige einzigartige haben. Ich habe eine Schnittstelle geschaffen, deren Namen diese ähnlichen Elemente wie zB: IAnimal Schnittstelle. Was ich normalerweise tun würde ist:

class dog : IAnimal

Aber es gibt 100 Klassen, und ich fühle mich nicht wie wenn sie gehen alle und suchen diejenigen, die ich IAnimal anwenden können.

Was ich tun möchte, ist dies:

dog scruffy = new dog();
cat ruffles = new cat();

IAnimal[] animals = new IAnimal[] {scruffy as IAnimal, ruffles as IAnimal} // gives null

oder

IAnimal[] animals = new IAnimal[] {(IAnimal)scruffy, (IAnimal)ruffles} //throws exception

Sie dann

foreach (IAnimal animal in animals)
{
   animal.eat();
}

Gibt es eine Möglichkeit c # machen lassen Sie mich als IAnimal Rüschen und vergammelt behandeln, ohne schreiben zu müssen. IAnimal wenn die Klasse zu schreiben

Danke!

EDIT (nicht faul): Die Klassen werden aus dem SQL-gespeicherte Prozedur Metadaten erzeugt, die jedes Mal bedeutet es erzeugt wird, ich hat sie in würde zurückgehen und hinzufügen oder den Code-Generator ändern, um die Mitglieder zu identifizieren, die in die Schnittstelle, das ist eigentlich keine schlechte Idee. Ich habe gehofft, es wurde jedoch eine Art von Generika Ansatz oder so etwas.

War es hilfreich?

Lösung

Sie können dieses Problem mit Teil-Klassen lösen : maschinengeneriertes / regenerierte Code lassen jeder Klasse in einer Quelldatei sein und die Hand codierte Teil (Definition der Subklassen von IAnimal) in eine andere.

Andere Tipps

Was Sie fordern Ente eingeben genannt wird, und ist nicht Teil von C # ich Angst habe. Jede Lösung wird Reflexion beinhalten und Blick auf den Eigenschaften, wird es schneller sein, die Klassen von Hand zu überprüfen, denke ich.

Es wäre ein interessantes Projekt sein, obwohl zu versuchen.

Die Lösung ist, den Code-Generator zu ändern. Zur Zeit ist es zu einfach für Ihre Bedürfnisse. Es sollte die Interface-Implementierung hinzufügen, wenn die entsprechenden Eigenschaften und / oder Methoden in der Klasse vorhanden sind.

Sie können einen Adapter erstellen, die „eat“ durch Reflexion, ein Arme-Leute-Ente eingeben greift:

public class Adapter<T> : IAnimal
{
   private T x;

   Adapter(T x)
   {
     this.x = x;
   }

   public void eat()
   {
     x.GetType().GetMethod("eat").Invoke(this);
   }
}

Dann können Sie es wie folgt verwendet werden:

dog scruffy = new dog();
cat ruffles = new cat();

IAnimal[] animals = new IAnimal[] {new Adapter<dog>(scruffy), new Adapter<cat>(ruffles )};

Nicht leicht, dass ich mir bewusst bin, Sie einen späten Bindung Anruf mithilfe von Reflektion tun könnten, aber Sie würden besser sein, Ihre Zeit zu verbringen, die Klassen Bearbeitung oder writting ein Makro, es zu tun.

Unter der Annahme, man kann wirklich nicht die Katze Klasse aus guten Gründen ändern,

Sie können einen Adapter für Katze schreiben, die von IAnimal geerbt dh:

  class cat_adapter : IAnimal
  {
       private cat baseCat;
       public cat_adapter( cat aCat)
       {
           baseCat = aCat;
       }

       // Implement IAnimal interface and redirect to baseCat
       public void eat()
       {
            baseCat.munchOnMeowMix();
       }

  }

In C ++ können Sie Vorlagen verwenden, vorausgesetzt alle generierten Klassen müssen die gleiche Funktion haben genannt:

  template <class BaseType>
  class CAnimalAdapter : public IAnimal
  {
  private:
        BaseType* m_baseInstance;
  public:
        CAnimalAdapter(BaseType* baseInstance) :
            m_baseInstance(baseInstance)
        {
        }

        void eat()
        {
            // You will get a compiler error if BaseType doesn't have this implemented
            baseInstance->doEat();                
        }

  }

Vielleicht mehr C # -py jemand als ich das gleiche mit Reflexion tun.

Wenn der Codegenerator die Klassen als Teil erzeugt, können Sie eine weitere Teil-Definition hinzuzufügen, die die Schnittstelle implementiert.

Nein. Es gibt keine Möglichkeit, C # erhalten können Sie dies tun zu lassen, ohne entweder eine konkrete Basisklasse mit oder einer Schnittstelle mit.

Ihre Klassen haben die Schnittstelle IAnimal zu implementieren. Eine Methode / Eigenschaft des gleichen Namens auf zwei verschiedenen Klassen werden nicht als gleichwertig, wenn sie beide Implementierungen einer Schnittstelle / Basisklasse sind.

Wenn Sie bereits die Methode implementiert und Sie wollen einfach nur die Schnittstelle implementieren, können Sie einen regulären Ausdruck verwenden, um mit Dateien ersetzen in-Befehl in der IDE.

Ansonsten nehmen Sie einen Blick auf Erweiterungsmethoden. Sie könnten passen Ihren Bedarf.

Wenn Sie die generierten Klassen als Teil Klassen implementieren, können Sie die Schnittstellen auf den dieser Klassen implementieren und dann Ihren Code-Generator ändern, um nur die Hälfte der Teilklasse zu erzeugen. Dies würde ermöglichen es Ihnen, Ihre Klassen zu regenerieren, ohne dass die Interface-Implementierung zu verlieren (oder jede andere benutzerdefinierte Logik Sie entscheiden hinzuzufügen).

Diese Art von Ansatz ist, wie LINQ to SQL-Klasse-Dateien erzeugen würde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top