更改界面是否会破坏现有客户端

时间:2016-09-02 15:05:56

标签: c# class interface

前言:此代码在Windows桌面应用程序,客户端/服务器应用程序中使用,其中服务器使用基于SMessage的类向/从客户端发送和接收消息

我有以下界面

public interface IMessage
{
    string ID { get; }

    string R_ID { get; set; }

    DateTime Send { get; }
}

以下是此界面的具体实现:

[Serializable]
public class SMessage : IMessage
{
    public string ID { get; set; }

    public string R_ID { get; set; }

    public DateTime Send{ get; set;}

    public SMessage()
    {
        R_ID = "";
        ID = Guid.NewGuid().ToString();
        Send = DateTime.UtcNow;
    }

    public SMessage(SMessage msg)
    {
        ID = msg.ID;
        Send = msg.UTCSend;
        R_ID = msg.R_ID;
    }

}

我已经使用上面的界面向全世界发布了软件,现在我需要在这个界面“Where”中添加一些额外的数据

public interface IMessage
{
string ID { get; }

string R_ID { get; set; }

DateTime Send { get; }

string Where { get; }
}

我的问题:添加此数据会破坏现场的现有客户吗?

如果是这样,我如何更新界面/具体类,以便现有客户端不会中断?

由于

其他信息:

SMessage是在应用程序中发送的其他消息的基类:

public class InstallMessage : SMessage
{
}

public class ChangeState : SMessage
{
}

如何避免破坏现有客户?

所以,如果我这样做:

public interface IMessage2 : IMessage
{
string Where { get; }
}

而且:

public class SMessage : IMessage2
{
 // the correct implementation for IMessage2 is added and omitted here for brevity
}

所以我不确定的是如何处理我不知道消息是否来自IMessage2的情况? (注意:此代码在客户端和服务器应用程序中)

现场的现有代码:

public void ReceiveChange( ChangeState msg )
{
    string x = msg.ID.ToString();
}

新代码将随后出现:

public void ReceiveChange( ChangeState msg )
{
    string x = msg.ID.ToString();

    // do I need to do some converting to keep from breaking ?
    IMessage2 iMsg = msg as IMessage2;
    if( iMsg2 != null )
    {
       string y = iMsg2.Where;
    }
}

由于

3 个答案:

答案 0 :(得分:1)

如果是在WebAPI方案中。

如果您依赖于接受IMessage作为参数的方法中新添加的字段,它将只会破坏现有客户端。

public void ServiceMethod(IMessage message) {
   if (message.Where == null)
      throw new ArgumentException("message.Where is null");
}

您可以向界面添加内容,只要您有正确处理缺失信息的代码,现有客户端就可以了。

处理此问题的正确方法是“版本”#39;您的服务和数据合同。我发现命名空间版本控制最容易维护。您将定义一个新的命名空间(比如v2)并重新定义实际更改的所有内容,方法,数据协定等。然后在路由中,将v2消息(http://acme.com/api/v2/messages)路由到新的命名空间,或者如果没有特别路由(http://acme.com/api/messages)将其路由到旧命名空间。

如果在直接引用的库中。

然后是 - 它会破坏现有客户。除非您的工厂生产具体实施可以确定客户想要的。类似于WebAPI路由的东西 - 但是对于直接引用的库。但这非常困难。

答案 1 :(得分:1)

您的界面的消费者不会抱怨,但实施将会。

如果您想避免这种情况,请创建一个新旧界面:

public interface INewMessage : IMessage
{
    string Where { get; set; }
}

答案 2 :(得分:0)

是的,如果他们使用不IMessage派生的SMessage使用自己的类,则会破坏现有客户端。这就是为什么Microsoft没有在版本之间更新.NET框架中的接口以添加新功能的原因。例如,在.NET 4.5中,DbDataReader获得了返回任务的新异步方法,但它们无法更新IDataReader,因为如果没有派生IDataReader,那么实施DbDataReader的任何人都会受到影响。

如果您不想破坏使用IMessage创建类但未使用SMessage的人的代码,则必须创建一个具有附加字段的新派生接口(例如,这是COM对象执行的操作,您经常会看到ISomeInterfaceISomeInterface2ISomeInterface3等)或根本不更新界面,只更新其他人可能派生的具体实现。< / p>