简体   繁体   English

相同的类,不同的命名空间,一种简化的方法?

[英]Same class, different namespaces, a way to simplify?

I'm working with a webservice that offers almost duplicated code across two namesspaces. 我正在使用一个Web服务,它在两个名称空间中提供几乎重复的代码。 Lets say for example PigFeet and HorseFeet, both namespaces contain a Feet class and other code that works with the Feet class requires it to be part of that same namespace. 让我们说例如PigFeet和HorseFeet,两个名称空间都包含一个Feet类,而其他与Feet类一起使用的代码要求它成为同一名称空间的一部分。

Right now In my code I'm forced to do something like this: 现在在我的代码中我被迫做这样的事情:

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

This is leaving me with lots of duplicated code. 这给我留下了许多重复的代码。 Is there a way to choose a namespace more dynamically? 有没有办法更动态地选择命名空间?

In your namespace imports you can assign an alias to a specific namespace or member. 在命名空间导入中,您可以为特定命名空间或成员分配别名

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

The namespace isn't the problem - it's simply that the 2 classes aren't related, so there's no inheritance chain that you can use for polymorphism. 命名空间不是问题 - 只是两个类没有关联,因此没有可用于多态的继承链。

You'll need to look at something like duck typing , or an adapter pattern , or building your own proxy classes to get yourself to a common interface. 您需要查看类似于鸭子类型适配器模式的内容 ,或者构建自己的代理类以使自己进入通用接口。 For small numbers of implementations, I've gotten away with just building a single adapter class that delegates to whatever non-null instance it has: 对于少量的实现,我已经完成了构建一个适配器类,该类委托给它拥有的任何非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());
      }
   }
}

For larger cases, you'd be better off with a separate PigFeetAdapter and HorseFeetAdapter that both implement IFeet, along with a FeetAdapterFactory to create them - but the concept is the same as I show above. 对于较大的情况,你最好使用一个单独的PigFeetAdapter和HorseFeetAdapter来实现IFeet,以及一个FeetAdapterFactory来创建它们 - 但这个概念与我在上面显示的相同。

Namespaces are just a way to organize your types. 命名空间只是一种组织类型的方法。 In your case you're having 2 or more different classes that have methods with the same signature but don't have a common interface. 在您的情况下,您有两个或更多不同的类,这些类具有相同签名但没有公共接口的方法。 In case you cannot change the code of the classes, the only way to avoid duplication here is to use reflection while loosing compile-time type-safety. 如果你不能改变类的代码,这里避免重复的唯一方法是在失去编译时类型安全的同时使用反射。

Here's me making things worse before making them better. 这让我在让它们变得更好之前让事情变得更糟。

You can encapsulate all the AnimalType decision logic in a single class. 您可以将所有AnimalType决策逻辑封装在一个类中。

Between the two types (PigsFeet and HorseFeet), there are some similiar methods... Since WashFeet has a common signature (void with no params), System.Action can be used to reference that method. 在两种类型(PigsFeet和HorseFeet)之间,有一些类似的方法......由于WashFeet有一个共同的签名(void没有参数),System.Action可以用来引用该方法。 Other methods with common signatures (and parameters) may require System.Func(T). 具有公共签名(和参数)的其他方法可能需要System.Func(T)。 Other methods without common signatures may need to be coerced into a common signature. 没有共同签名的其他方法可能需要被强制转换为共同签名。

Here's the client code: 这是客户端代码:

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

Here's the encapsulation class. 这是封装类。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM