1

概要

私は2つの主要な抽象化レベルを使用するアプリケーションに取り組んでいます:

  • コアライブラリはいくつかのインターフェイスを定義し、インターフェイスの観点からコア機能を実装するクラスを含みます。このように、コアアルゴリズムを一度作成したいと思いますが、それらを任意の数のインターフェイス実装に適用できるようにします。
  • 「実装」ライブラリは、サードパーティのSDKを使用して、一連のインターフェイスの1つの特定の実装を提供します。最終的には、これらのライブラリが複数存在することになります。どちらを使用するかは、構成によって決まります。

アプリケーション自体がSDKライブラリからクラスをインスタンス化し、それらを使用してコアライブラリの依存関係を満たします。

問題

私が解決する必要のある問題は、一般的に次のようになります。

// Algorithm in the core (interfaces are all implemented by the SDK library):
ICorrespondentRepository allCorrespondents = ...;
ICorrespondent correspondent = allCorrespondents.FindByName(...);
...
IDocumentRepository allDocuments = ...;
IDocument document = allDocuments.FindByTitle(...);

// Problem: Implementation needs state not exposed
// on ICorrespondent in order to do this:
document.SetRecipient(correspondent);

つまりIDocument、受信者を以前に取得したに設定することができますICorrespondent。がSetRecipient呼び出されると、実際に変更を行うために、IDocument-に関連付けられているが-によって公開されていないニーズ状態(コアにとって重要ではない主キー)の実装が必要になります。ICorrespondent

ICorrespondentこれを行う1つの方法は、内部の実際の実装クラスにダウンキャストすることですSetRecipientが、これは非常に扱いにくいと感じます。さらに悪いことに、インターフェイス参照から内部状態へのマップを保持します。

問題の根本は、インターフェースが、コアとそれを生成した実装ライブラリという、要件の異なる2つのコンシューマーを効果的に持っているにもかかわらず、コアライブラリの一般的なニーズに対応するように排他的に設計されていることです。

この種の要件を再設計するためのより良い方法はありますか?

4

1 に答える 1

1

実際、あなたがやりたいのはクロスキャスティングです。

の特定の実装はのIDocumentすべてのサブクラスと互換性があるわけではないため、渡されたインスタンスにこの主キーがない場合、ICorrespondentへの呼び出しSetRecipientは合法的に失敗する可能性があります。ICorrespondentこの主キーを持つことは、互換性のあるサブクラスの「特性」です。

あなたが使うかもしれないテクニックはこれです。インターフェイスを定義します。

internal interface IHasPrimaryKey {
    PrimaryKey GetPrimaryKey();
}

また、互換性のあるICorrespondentクラスは両方のインターフェースを実装する必要があります。

internal class CompatibleCorrespondent : ICorrespondent, IHasPrimaryKey {
    // ...
}

この場合、SetRecipientコレスポンデントのクロスキャストを試して、必要な主キーが提供されているかどうかを確認し、そうでない場合は失敗する必要があります。

var hasPrimaryKey = correspondent as IHasPrimaryKey;
if(hasPrimaryKey == null) {
    throw new InappropriateSubclassException();
}
// ...
var pk = hasPrimaryKey.GetPrimaryKey();

これは、この種のアーキテクチャから抜け出すことができる最も強く型付けされたソリューションです。タイプシステムは、すべての場合に主キーを取得することを保証しないため、失敗のケースは正当です。

これには、特定のサブクラスにバインドされないという利点があります。ICorrespondentとの両方を実装する任意のクラスIHasPrimaryKeyが適しています。

もちろん、特定のコードに適した名前を見つけることができます。

于 2013-05-16T13:46:20.093 に答える