Один и тот же класс, разные пространства имен, способ упрощения? - PullRequest
3 голосов
/ 05 октября 2008

Я работаю с веб-сервисом, который предлагает почти дублированный код в двух пространствах имен. Скажем, например, PigFeet и HorseFeet, оба пространства имен содержат класс Feet, а другой код, который работает с классом Feet, требует, чтобы он был частью этого же пространства имен.

Прямо сейчас В моем коде я вынужден сделать что-то вроде этого:

if( _animalType == AnimalType.Pig )
{ 
     //namespace is pigfeet
     PigFeet.Feet feet = new Feet();
     feet.WashFeet();
}

if( _animalType == AnimalType.Horse )
{
     //namespace is horsefeet
     HorseFeet.Feet feet = new Feet();
     feet.WashFeet();
 }

Это оставляет у меня много дублированного кода. Есть ли способ выбрать пространство имен более динамично?

Ответы [ 4 ]

3 голосов
/ 05 октября 2008

В импорте пространства имен вы можете назначить псевдоним для определенного пространства имен или члена.

using PigFeet = PigFeet.Feet;
using HorseFeet = HorseFeet.Feet;

//now your sample code should look something like

if( _animalType == AnimalType.Pig )
{ 
     //namespace is pigfeet
     PigFeet feet = new PigFeet();
     feet.WashFeet();
}

if( _animalType == AnimalType.Horse )
{
     //namespace is horsefeet
     HorseFeet feet = new HorseFeet();
     feet.WashFeet();
 }
2 голосов
/ 05 октября 2008

Пространство имен не проблема - просто два класса не связаны, поэтому нет цепочки наследования, которую вы можете использовать для полиморфизма.

Вам нужно будет посмотреть на что-то вроде утка, набрав , или шаблон адаптера , или создать собственные прокси-классы, чтобы получить общий интерфейс. Для небольшого числа реализаций мне просто удалось создать один класс адаптера, который делегирует любому непустому экземпляру:

interface IFeet {
   void WashFeet();
}

class FeetAdapter : IFeet {
   private PigFeet.Feet _pigFeet;
   private HorseFeet.Feet _horseFeet;

   private FeetAdapter(PigFeet.Feet pigFeet) {
      _pigFeet = pigFeet;
   }

   private FeetAdapter(HorseFeet.Feet horseFeet) {
      _horseFeet = horseFeet;
   }

   public void WashFeet() {
      if (_pigFeet != null) {
         _pigFeet.WashFeet();
      } else {
         _horseFeet.WashFeet();
      }
   }

   public static FeetAdapter Create(AnimalType animalType) {
      switch (animalType) {
         case AnimalType.Pig:
            return new FeetAdapter(new PigFeet.Feet());
         case AnimalType.Horse:
            return new FeetAdapter(new HorseFeet.Feet());
      }
   }
}

В более крупных случаях лучше использовать отдельные PigFeetAdapter и HorseFeetAdapter, которые оба реализуют IFeet, а также FeetAdapterFactory для их создания - но концепция такая же, как я показываю выше.

0 голосов
/ 05 октября 2008

Вот я делаю вещи хуже, прежде чем сделать их лучше.

Вы можете инкапсулировать всю логику принятия решений AnimalType в одном классе.

Между двумя типами (PigsFeet и HorseFeet) есть несколько похожих методов ... Поскольку WashFeet имеет общую подпись (void без параметров), System.Action можно использовать для ссылки на этот метод. Другие методы с общими сигнатурами (и параметрами) могут требовать System.Func (T). Другие методы без общих подписей, возможно, придется привести к общей подписи.

Вот код клиента:

AnimalFeetFacade myFacade = new AnimalFeetFacade(_animalType);
myFacade.WashFeet();

Вот класс инкапсуляции.

public class AnimalFeetFacade
{
  public AnimalFeetFacade(AnimalType theType)
  {
    if (theType == AnimalType.Pig)
    {
      _washFeet = WashPigFeet;
      //TODO reference more PigFeet methods here
    }
    else if (theType == AnimalType.Horse)
    {
       _washFeet = WashHorseFeet;
       //TODO reference more HorseFeet methods here
    }
    else
    {
       throw new NotImplementedException("AnimalFeetFacade only works with PigFeet and HorseFeet");
    }
  }

  protected Action _washFeet;

  public void WashFeet()
  {
    _washFeet.Invoke();
  }

  protected void WashPigFeet()
  {
    PigFeet.Feet = new PigFeet.Feet()
    feet.WashFeet()
  } 

  protected void WashHorseFeet()
  {
    HorseFeet.Feet = new HorseFeet.Feet()
    feet.WashFeet()
  }
}
0 голосов
/ 05 октября 2008

Пространства имен - это просто способ упорядочить ваши типы. В вашем случае у вас есть 2 или более разных классов, которые имеют методы с одинаковой сигнатурой, но не имеют общего интерфейса. В случае, если вы не можете изменить код классов, единственный способ избежать дублирования здесь - это использовать отражение, теряя безопасность типов во время компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...