SOAを使用してオブジェクトモデルにリモートアクセスしようとしているようです。サービスに公開させたい相互作用と機能を確認し、サービス実装の継承の詳細を公開しないようにすることをお勧めします。
したがって、ユーザーアカウントのリストが必要なこの場合、インターフェイスは次のようになります。
[ServiceContract]
interface ISomeService
{
[OperationContract]
Collection<AccountSummary> ListAccountsForUser(
User user /*This information could be out of band in a claim*/);
}
[DataContract]
class AccountSummary
{
[DataMember]
public string AccountNumber {get;set;}
[DataMember]
public string AccountType {get;set;}
//Other account summary information
}
継承ルートを使用する場合は、KnownType属性を使用できますが、これにより、ネットワークを介して送信されるメッセージにタイプ情報が追加され、相互運用性が制限される場合があることに注意してください。
更新:
以前に答えたときは少し時間が限られていたので、なぜこのスタイルを好むのかを詳しく説明します。
OOADをDTOを介して別のレイヤーに公開することはお勧めしません。これにより、通常、使用されていない大量のデータを渡し、ドメインモデルの本質的なコピーとの間でデータを忠実にマッピングする、肥大化したインターフェイスが発生します。すべてのロジックが削除され、値が表示されません。私は通常、公開する操作を中心にサービスレイヤーを設計し、サービスの相互作用の定義にDTOを使用します。
ドメインモデルではなく公開された操作に基づいてDTOを使用すると、サービスのカプセル化を維持し、ドメインモデルへの結合を減らすことができます。ドメインモデルを公開しないことで、シリアル化のためにフィールドの可視性や継承について妥協する必要がなくなります。
たとえば、あるアカウントから別のアカウントへの転送メソッドを公開している場合、サービスインターフェイスは次のようになります。
[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(TransferRequest request);
}
[DataContract]
class TransferRequest
{
[DataMember]
public string FromAccountNumber {get;set;}
[DataMember]
public string ToAccountNumber {get;set;}
[DataMember]
public Money Amount {get;set;}
}
class SomeService : ISomeService
{
TransferResult Transfer(TransferRequest request)
{
//Check parameters...omitted for clarity
var from = repository.Load<Account>(request.FromAccountNumber);
//Assert that the caller is authorised to request transfer on this account
var to = repository.Load<Account>(request.ToAccountNumber);
from.Transfer(to, request.Amount);
//Build an appropriate response (or fault)
}
}
これで、このインターフェースから、この操作を呼び出すために必要なデータが何であるかが、消費者にとって非常に明確になります。これを次のように実装した場合
[ServiceContract]
interface ISomeService
{
[OperationContract]
TransferResult Transfer(AccountDto from, AccountDto to, MoneyDto dto);
}
AccountDtoは、コンシューマーとしてのアカウント内のフィールドのコピーです。どのフィールドに入力する必要がありますか?それらすべて?新しい操作をサポートするために新しいプロパティが追加された場合、すべての操作のすべてのユーザーがこのプロパティを表示できるようになります。WCFを使用すると、このプロパティを非必須としてマークして、他のすべてのクライアントを壊さないようにすることができますが、新しい操作に必須の場合、クライアントは操作を呼び出したときにのみ検出されます。
さらに悪いことに、サービスの実装者として、現在の残高が提供された場合はどうなりますか?私はそれを信頼すべきですか?
ここでの一般的なルールは、データ、クライアント、またはサービスの所有者を尋ねることです。クライアントがそれを所有している場合、それをサービスに渡すことができ、いくつかの基本的なチェックを行った後、サービスはそれを使用できます。サービスがそれを所有している場合、クライアントは、サービスが必要なものを取得するのに十分な情報のみを渡す必要があります。これにより、サービスは所有するデータの整合性を維持できます。
この例では、サービスがアカウント情報を所有しており、それを見つけるためのキーはアカウント番号です。サービスは金額(正、サポートされている通貨など)を検証する場合がありますが、これはクライアントが所有しているため、DTOのすべてのフィールドに入力されることが期待されます。
要約すると、3つの方法すべてが実行されていることを確認しましたが、特定の操作を中心にDTOを設計することは、サービスとコンシューマーの両方の実装で最も成功しています。これにより、操作を独立して進化させることができ、サービスによって何が期待され、何がクライアントに返されるかについて非常に明確になります。