3

我正在使用一个跨两个命名空间提供几乎重复代码的 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

命名空间不是问题——只是这两个类不相关,因此没有可用于多态性的继承链。

您将需要查看诸如鸭子类型适配器模式之类的东西,或者构建您自己的代理类以使自己获得一个通用接口。对于少量的实现,我只是构建了一个适配器类,它委托给它拥有的任何非空实例:

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 来创建它们——但这个概念和我上面展示的一样。

于 2008-10-05T18:07:00.083 回答
0

命名空间只是组织类型的一种方式。在您的情况下,您有 2 个或更多不同的类,它们的方法具有相同的签名但没有通用接口。如果您无法更改类的代码,避免重复的唯一方法是在失去编译时类型安全的同时使用反射。

于 2008-10-05T17:54:28.157 回答
0

这是我在让事情变得更好之前让事情变得更糟。

您可以将所有 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()
  }
}
于 2008-10-05T18:20:22.693 回答