2016-09-02 4 views
2

序文を変えます。このコードは、サーバーがSMessageを使用してクライアントへの/からのメッセージを送信し、受信したWindowsデスクトップアプリケーション、クライアント/サーバアプリケーション、ベースクラスは、インタフェースブレーク既存のクライアントに

内で使用されて、私は次のようしていますインタフェース

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

} 

私が使用して世界にソフトウェアをリリースしていますインターフェイス上で、今、私は「」

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のものかどうか(注:このコードは、クライアントとサーバーのアプリケーションである)]フィールド

既存のコード:NEXTバージョンで送信されます

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

NEW CODE:

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

私は、派生型の「SMessage」(封印されていない)を作成したクライアントを破ることしかできないと思います。 – itsme86

+1

プログラマーで[versioning interfaces](http://programmers.stackexchange.com/questions/138948/how-do-you-evolve-version-an-interface)を読んでください。 – kayess

+0

あなたの更新のために、あなたはキャストする必要もなく、 'msg'はすでに' .yhere'を公開することができます。 'string y = msg.Where;'は問題ありません。 'ReceiveChange'が' ChangeState'の代わりに 'IMessage'を受け取った場合にのみ、キャストを行う必要があります。 (また、あなたのキャストが間違っていると、例外が発生します。IMessage2 iMsg = msgはIMessage2;としてください。キャストに失敗した場合、 'as'は通常のキャストが実行時例外をスローする場合にnullを返します。 ) –

答えて

1

あなたのインターフェイスの消費者が文句を言うことはありませんが、実装はされます。彼らはIMessageを使用し、独自のクラスをimplmented場合はそうでない

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

WebAPIシナリオの場合。

パラメータとしてIMessageを受け入れるメソッドの新しく追加されたフィールドに依存している場合、既存のクライアントのみが破損します。

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

あなたは、インターフェイスに物事を追加することができますし、限り、あなたは適切に不足している情報を処理するコードを持っているとして、既存のクライアントは罰金になります。

これを処理する適切な方法は、サービスとデータの契約を「バージョン化」することです。私は名前空間を維持するのが最も容易であることがわかります。新しい名前空間(v2)を定義し、実際に変更されたもの、メソッド、データコントラクトなどを再定義します。あなたのルーティングでは、v2メッセージ(http://acme.com/api/v2/messages)を新しい名前空間にルーティングするか、特別にルーティングされていない場合は(http://acme.com/api/messages)古い名前空間にルーティングします。

直接参照されるライブラリの場合、

はい - 既存のクライアントが破損します。具体的な実装を生成するファクトリが、クライアントが望むものを決定できない限り。 WebAPIルーティングに似ていますが、直接参照されるライブラリの場合。しかし、これは非常に困難です。

0

はい、それは既存のクライアントを解除されます:あなたはこれを避けたい場合は

、古いものから拡張する新しいインターフェイスを作成しますSMessageに由来します。これは、Microsoftが新しい機能を追加するためにバージョン間の.NETフレームワークのインターフェイスを更新していない理由です。たとえば、.NET 4.5 DbDataReaderでタスクを返された新しい非同期メソッドを得たが、それはDbDataReaderから派生せずにIDataReaderを実現し、誰が壊れていたので、彼らはIDataReaderを更新できませんでした。

IMessageを使用してクラスを作成したユーザーのコードを破損したくない場合は、SMessageを使用せずに、追加のフィールドを持つ新しい派生インターフェイスを作成する必要があります(たとえば、これはCOMオブジェクトの操作です。多くの場合、ISomeInterfaceISomeInterface2ISomeInterface3などを参照してください)、インターフェイスを更新しないでください。他の人が派生した具体的な実装のみを更新します。

+0

これは、MicrosoftがIDataReaderの実装を作成して返すファクトリを実装しておらず、バージョン管理も実装していないからです。すべての実装が直接インスタンス化されます。ファクトリを使用してインターフェイスの具体的な実装をインスタンス化すると、バージョン管理を使用してインターフェイスを変更できます。 – rick

+0

@rick私はデータリーダーを直接作成したことは一度もありません。これは常に '.ExecuteDataReader()'や '.ToDataReader()'ファクトリメソッドから来ています。 –

+0

はい、あなたは絶対に正しいです。しかし、これらのメソッドはIDataReaderではなくDbDataReaderの具象クラスを返します。そこにはその要点があります。 – rick

関連する問題