3

私は、2つの名前空間でほぼ重複したコードを提供するWebサービスを使用しています。たとえば、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

4 に答える 4

3

名前空間のインポートでは、特定の名前空間またはメンバーにエイリアスを割り当てることができます。

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();
 }
于 2008-10-05T17:25:26.860 に答える
2

名前空間は問題ではありません。単純に 2 つのクラスが関連していないため、ポリモーフィズムに使用できる継承チェーンがありません。

ダック タイピングアダプター パターン、独自のプロキシ クラスの作成などを調べて、共通のインターフェイスにアクセスする必要があります。実装の数が少ない場合は、null 以外のインスタンスに委譲する単一のアダプター クラスを作成するだけで済みました。

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

より大きなケースでは、IFeet を実装する別の PigFeetAdapter と HorseFeetAdapter と、それらを作成するための FeetAdapterFactory を使用したほうがよいでしょうが、概念は上で示したものと同じです。

于 2008-10-05T18:07:00.083 に答える
0

名前空間は、タイプを整理するための単なる方法です。あなたの場合、同じ署名を持つメソッドを持っているが、共通のインターフェースを持たない2つ以上の異なるクラスがあります。クラスのコードを変更できない場合、ここで重複を回避する唯一の方法は、コンパイル時の型安全性を失いながらリフレクションを使用することです。

于 2008-10-05T17:54:28.157 に答える
0

ここでは、物事を良くする前に、物事を悪化させています。

すべての AnimalType 決定ロジックを 1 つのクラスにカプセル化できます。

2 つのタイプ (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()
  }
}
于 2008-10-05T18:20:22.693 に答える