Question

J'ai 100 classes qui ont des éléments similaires et des éléments uniques. J'ai créé une interface qui nomme ces éléments similaires, par exemple: interface IAnimal. Ce que je ferais normalement est:

class dog : IAnimal

Mais il y a 100 classes et je n'ai pas envie de les consulter toutes et de rechercher celles auxquelles je peux appliquer IAnimal.

Ce que je veux faire, c'est ceci:

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

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

ou

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

puis faites

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

Existe-t-il un moyen de faire en sorte que c # me permette de traiter les volants et les décolletés comme un IAnimal sans avoir à écrire: IAnimal lors de l'écriture du cours.

Merci!

EDIT (non paresseux): les classes sont générées à partir de métadonnées proc stockées dans SQL, ce qui signifie que chaque fois qu'elle est générée, je devrais revenir en arrière et les ajouter ou modifier le générateur de code pour identifier les membres qui se trouvent dans l'interface, en fait, ce n'est pas une mauvaise idée. J'espérais qu'il y avait une sorte d'approche générique ou quelque chose cependant.

Était-ce utile?

La solution

Vous pourriez résoudre ce problème avec les classes partielles : laissez le code généré / régénéré par la machine dans un fichier source de chaque classe et la partie codée à la main (définissant le sous-classement à partir de IAnimal) dans un autre.

Autres conseils

Ce que vous demandez, c’est ce que l’on appelle la saisie au canard et ne fait pas partie du C #, j’ai peur. Toute solution impliquera réflexion et examen des propriétés. Il sera plus rapide de vérifier les classes à la main, je pense.

Ce serait un projet intéressant d'essayer cependant.

La solution consiste à modifier le générateur de code. Actuellement, c'est trop simpliste pour vos besoins. Il convient d’ajouter l’implémentation d’interface si les propriétés et / ou les méthodes pertinentes sont présentes dans la classe.

Vous pouvez créer un adaptateur qui accède à " eat " par la réflexion, un pauvre homme tapant du canard:

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

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

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

Ensuite, vous pouvez l'utiliser comme ceci:

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

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

Pas à ma connaissance, vous pouvez passer un appel de liaison tardif en utilisant la réflexion, mais vous feriez mieux de passer votre temps à éditer les classes ou à écrire une macro pour le faire.

En supposant que vous ne puissiez vraiment pas modifier la classe de chats pour de bonnes raisons,

Vous pouvez écrire un adaptateur pour chat hérité de IAnimal, à savoir:

  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();
       }

  }

En C ++, vous pouvez utiliser des modèles en supposant que toutes les classes générées doivent avoir la même fonction, appelée

.
  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();                
        }

  }

Peut-être que quelqu'un de plus grand que moi pourra faire de même avec la réflexion.

Si le générateur de code génère les classes en tant que partielles, vous pouvez ajouter une autre définition partielle qui implémente l'interface.

Non. Il n’ya aucun moyen de faire en sorte que C # vous le permette sans avoir une classe de base concrète ou une interface.

Vos classes doivent implémenter l'interface IAnimal. Une méthode / propriété du même nom sur deux classes différentes ne sont considérées comme équivalentes que si elles sont les deux implémentations d’une classe d’interface / base.

Si vous avez déjà implémenté la méthode et souhaitez simplement implémenter l'interface, vous pouvez utiliser une expression régulière avec la commande replace in files dans votre IDE.

Sinon, jetez un coup d'œil aux méthodes d'extension. Ils pourraient correspondre à vos besoins.

Si vous implémentez les classes générées sous forme de classes partielles, vous pouvez implémenter les interfaces sur ces classes, puis modifier votre générateur de code pour ne générer que la moitié de la classe partielle. Cela vous permettrait de régénérer vos classes sans perdre l'implémentation de l'interface (ou toute autre logique personnalisée que vous décidez d'ajouter).

Ce type d’approche permet à LINQ to SQL de générer des fichiers de classe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top