在客户端和服务器端实现接口

时间:2013-10-22 16:34:18

标签: c# oop design-patterns interface client-server

我有一个客户端(Android应用程序)和一个服务器(WebApi REST Web服务)。

该应用程序有一个服务层,它调用该服务层与Web服务进行通信以读取和写入记录。返回值从Web服务的控制器发回(即,当新记录写入DB并生成关联的记录ID时)。

我有许多不同的控制器,每个控制器都有多个方法,它们都返回不同数量和类型的值(它们主要返回int数组,但如果混合了非整数值,偶尔会返回一个对象数组)。

应用程序端的服务层执行一些检查以验证参数,例如检查参数count(数组元素)并检查预定义的无效/未初始化值(如-9999)。

我不想通过定义一个接口来形式化这些参数操作,这样就可以在一个位置明确指定两侧使用的参数的计数和类型(所以我不是两边都是“翼展”) )。

但是,我遇到的困境是决定是否定义一个指定客户端和服务器相关方法的接口,或者定义两个单独的接口,每个接口都指定特定于通信方面的方法。

如果我有一个界面,就像这样:

public interface IServiceParams
{
   object[] CreateParams(int recordId, string recordNumber);

   bool ParseParams(object[] paramz, out int recordId, out string recordNumber);
}

那么因为CreateParams只在WS端使用,而在App端使用ParseParams,所以我必须在两边声明空实现

Web服务方:

public class RecordController : ApiController, IServiceParams
{
   object[] IServiceParams.CreateParams(int recordId, string recordNumber)
   {
      return new[] { newRecordId, newRecordNumber };
   }

   bool IServiceParams.ParseParams(object[] paramz, out int recordId, out string recordNumber)
   {
      throw new NotImpementedException();
   }

   ////////////////////////////////////////////////////////////////////////////////////////////

   public object[] Put( Record record )
   {
      if( !DbLayer.Update(record) )
      {
         return null;
      }

      return CreateParams(record.RecordId, record.RecordNumber);
   }
}

App Side:

public class RecordService : IServiceParams
{
   object[] IServiceParams.CreateParams(int recordId, string recordNumber)
   {
      throw new NotImpementedException();
   }

   bool IServiceParams.ParseParams(object[] paramz, out string recordNumber)
   {
      if( paramz == null || paramz.Count != 4 )
      {
         return false;
      }

      if(!ParseInt(paramz[0].ToString(), out recordId) || recordIdNew == DEFAULT_RECORD_ID)
      {
         return false;
      }

      // ...

      return true;
   }

   ////////////////////////////////////////////////////////////////////////////////////////////

   public bool UpdateRecord( Record record )
   {
      object[] paramz = WebService.Put( record );

      int recordId; 
      string recordNumber;

      if(!ParseParams(paramz, out recordId, out recordNumber))
      { 
         return false;
      }

      record.RecordId = recordId;
      record.RecordNumber = recordNumber;

      return true;
   }
}    

或者,我应该定义两个接口,并在各自的侧面实现每个接口,从而消除了空实现的需要:

public interface IServiceParamsClient
{
   bool ParseParams(object[] paramz, out int recordId, out string recordNumber );
}

public interface IServiceParamsServer
{
   object[] CreateParams(int recordId, string recordNumber);
}

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您是否有任何理由需要在一个界面中声明这两种方法?如果没有,请创建两个独立的接口,每个接口反映其意图。必须实现“不支持”的方法是一种设计气味。 请参阅:What's the right way to design my interface when I have operations that aren't supported by all implementers?

答案 1 :(得分:1)

进行两种界面设计。通过这样做,您可以使用更干净的API来帮助自己。一个建议是你可以将参数逻辑封装在一个类中,这样现在你有一个更强大的类型静态检查,这不是一件小事。其次,我不确定Web服务是否了解App客户端是一件好事。我认为应该是另一种方式。所以我会这样做:

public class Param //at server side
{
   public int recordId { get; set; }
   public int transToPropId { get; set; }
   public int receivedViaTypeId { get; set; }
   public string recordNumber { get; set; }
}

public interface IParamParser //at client
{
   //I do not know what object[] paramz is; I leave that to you; 
   //may be it needs encapsulation as well
   bool Parse(object[] paramz, Param p);
}

public interface IParamCreator //at server
{
   Param CreateParams(int recordId, int transToPropId, int receivedViaTypeId, 
                      string recordNumber);
}