前言:此代码在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;
}
}
由于
答案 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对象执行的操作,您经常会看到ISomeInterface
,ISomeInterface2
,ISomeInterface3
等)或根本不更新界面,只更新其他人可能派生的具体实现。< / p>