Pergunta

Eu tenho 100 classes que têm alguns elementos semelhantes e alguns únicos. Eu criei uma interface que nomeia esses itens semelhantes, por exemplo: interface Ianimal. O que eu normalmente faria é:

class dog : IAnimal

Mas existem 100 aulas e não sinto vontade de ir a todas elas e procurar as que posso aplicar Ianimal.

O que eu quero fazer é o seguinte:

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

então faça

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

Existe uma maneira de fazer C# Deixe -me tratar babados e desalinhados como um Ianimal sem ter que escrever: Ianimal ao escrever a aula.

Obrigado!

Editar (não preguiçoso): as classes são geradas com os metadados do SQL armazenados, o que significa que toda vez que é gerado, eu teria que voltar e adicioná -los ou modificar o gerador de código para identificar os membros que estão na interface, Na verdade, isso não é uma má ideia. Eu esperava que houvesse algum tipo de abordagem de genéricos ou algo assim.

Foi útil?

Solução

Você pode resolver esse problema com classes parciais: Deixe o código gerado/regenerado gerado por máquina estar em um arquivo de origem de cada classe e a parte codificada à mão (definindo a subclasse de Ianimal) em outra.

Outras dicas

O que você está pedindo é chamado de digitação de pato e não faz parte do C#, eu tenho medo. Qualquer solução envolverá reflexão e observar as propriedades, será mais rápido verificar as aulas manualmente, eu acho.

Seria um projeto interessante tentar.

A solução é modificar o gerador de código. Atualmente, é muito simplista para suas necessidades. Ele deve adicionar a implementação da interface se as propriedades e/ou métodos relevantes estiverem presentes na classe.

Você pode criar um adaptador que acessa "eat"Através da reflexão, a digitação de pato de um homem pobre:

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

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

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

Então você pode usá -lo assim:

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

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

Não é fácil que eu conheço, você pode fazer uma chamada de ligação tardia usando a reflexão, mas seria melhor gastar seu tempo editando as aulas ou escrevendo uma macro para fazê -lo.

Supondo que você realmente não possa modificar a classe CAT por boas razões,

Você poderia escrever um adaptador para o gato que herdou de Ianimal, ou seja:

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

  }

Em C ++, você pode usar modelos assumindo que todas as suas classes geradas precisam ter a mesma função chamada:

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

  }

Talvez alguém mais C#-py do que eu possa fazer o mesmo com reflexão.

Se o gerador de código gerar as classes como parcial, você poderá adicionar outra definição parcial que implementa a interface.

No. There is no way you can get C# to let you do this without either having a concrete base class or having an interface.

Your classes have to implement the interface IAnimal. A method/property of the same name on two different classes are not considered equivalent unless they are both implementations of an interface/base class.

If you have already implemented the method and you just want to implement the interface, you can use a regular expression with replace in files command in your IDE.

Otherwise, take a look at extension methods. They might fit your need.

If you implement the generated classes as partial classes, you could implement the interfaces on the these classes and then change your code generator to only generate half of the partial class. This would allow you to regenerate your classes without losing the interface implementation (or any other custom logic you decide to add).

This type of approach is how LINQ to SQL would generate class files.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top