0

最初に長い質問で申し訳ありません。より短い質問を考え出したいと思いますが、これは私が提供できる最も単純なバージョンであり、私の主張を明確に説明できます.

複数のサービスを提供する必要があるラッパーサービスをクライアントに提供しようとしています。その背後にあるアイデアは、複数の呼び出しを 1 つの呼び出しに減らし、他の関連付けられたオブジェクトを含む単一のオブジェクトを返すことです。私の要点を説明するために、次の例を挙げましょう。

次のサービスがあるとします。

  • MyCompany.Services.Donation
  • MyCompany.Services.Payment
  • MyCompany.Services.PartialPayment

通常、クライアントは Donation サービス (donationID を使用) にクエリを実行して寄付情報を取得し、取得した寄付情報を使用して Payment サービスにクエリを実行し、支払い関連の詳細を取得する必要があります。 、特定の寄付者のすべての寄付情報を取得するには、PartialPayment サービスにクエリを実行する必要があります。

クライアントがこれを行う代わりに、donationID を単一のパラメーターとして受け入れ、次のようなクラスを返すラッパー サービスを提供します。

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class DonationDetail
{
     [DataMember]
     public MyCompany.Services.Donation.Record donationRecord;
     [DataMember]
     public PaymentDetail paymentDetail;    
}

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class PaymentDetail
{
     [DataMember]
     public MyCompany.Services.Payment.Record paymentRecord;
     [DataMember]
     public List<MyCompany.Services.PartialPayment.Record> partialPayments;
}

したがって、DonationDetail レコードのインスタンスは、その寄付に関連するすべての情報を返す必要があります。

ラッパーサービスを使用してクライアントに渡すクラスはすべてラッパーサービスの一部になり、クライアントはサービス参照を使用せずに取得した対応するタイプでそれらをすぐに使用できないため、ラッパーサービスでこれらの個々のサービス DLL を使用すると問題が発生します。ある型を別の型に変換するためのカスタム構築メソッドを作成する - それらは同じオブジェクトですが。元の名前空間のクラスを参照する代わりに、サービスは上記のクラスに対して次のようなクラスを使用します。

  • DonationDetail.Record (寄付記録 - MyCompany.Services.Donation.Record を期待します)
  • DonationDetail.Record1 (支払いレコード - MyCompany.Services.Payment .Record が必要です)
  • DonationDetail.Record2 (PartialPayment レコード - MyCompany.Services.PartialPayment.Record を期待します)

カスタムコンストラクターなしでそのようなインターフェースを提供する方法はありますか? では、MyCompany.Services.PartialPayment WCF サービスに "PartialPayment" 名前空間を使用する場合、DonationDetail がラッパー サービスを介して取得された後、以下のことを行うことができますか?

PartialPayment.Record partialPayment = dDetailObj.paymentDetail.partialPayments[0];

*: それが問題の原因でない限り、サービス参照を使用しない理由を聞かないでください。そのオプションは、この時点で他の問題を引き起こすためです)

4

1 に答える 1

2

したがって、あなたが言っていることは、事実上、同じオブジェクトを返す2つの異なるサービスがあり、これを2つの異なるサービス参照としてクライアントに追加すると、サービスに関する限り最終的には同じオブジェクトであるにもかかわらず、ということです。 (同じ DLL を参照するため) 関係があるため、クライアントはそれらを 2 つの異なる型と見なすため、一方から返されたオブジェクトを取得して、もう一方のサービスへの入力として送信することはできません。

私があなたの質問を理解したと仮定します(理解していない場合は申し訳ありません)...

あるタイプを構築してプロパティを設定することで、あるタイプを別のタイプにマッピングできますが、それは本当に面倒であり、消費者にとってあまり友好的ではありません。したがって、私は何か根本的なことを提案します...

クライアントでのサービス参照を破棄します。

うん、言った、どうしてそんなことを提案するの!?! これが理由です...

まず、プロジェクトが次のように構成されていることを確認します。

寄付の詳細クライアント ライブラリ

  • IDonationService (これはサービス コントラクトです。クライアント ライブラリに実装がないことに注意してください)
  • 寄付実績

支払い詳細クライアント ライブラリ

  • IPaymentService (これはサービス コントラクトです。クライアント ライブラリに実装がないことに注意してください)
  • 支払記録

一部支払いクライアント ライブラリ

  • IPartialPaymentService (これはサービス コントラクトです。クライアント ライブラリに実装がないことに注意してください)
  • 一部支払記録

ラッパー サービス クライアント ライブラリ (他の 3 つのクライアント ライブラリを参照)

  • IWrapperService (これはサービス コントラクトです。クライアント ライブラリに実装がないことに注意してください)

ちなみに、レコードには異なるクラス名を付けましたが、必要に応じて名前空間を使用して、それらをすべて Record と呼ぶこともできます (異なる名前を付けた方が混乱が少ないと思いますが、それはおそらく私だけです)。

サービス側では、サービスを実装するために必要なクライアント ライブラリを参照し、いつものように必要なことをすべて実行します。

クライアントでは、同じ方法でクライアントライブラリ(または呼び出したいサービスに応じてライブラリ)も参照します(したがって、サーバーとクライアントの間に効果的に共有ライブラリがあります-古い学校ですが、理由がわかります)。

クライアントには、サービス コントラクトとすべてのデータ コントラクトのインターフェイスがあるため、サービス参照全体や生成されたコードは必要ありません。代わりに、クライアントでできることは次のようなものです。

DonationRecord donation;

using (var cf = new ChannelFactory<IDonationService>("EndpointNameInConfigurationFile"))
{
    IDonationService donationservice = cf.CreateChannel();
    donation = donationservice.GetDonation("Donation1234");
}

using (var cf = new ChannelFactory<IWrapperService>("EndpointNameInConfigurationFile"))
{
    IWrapperService wrapperService = cf.CreateChannel();
    wrapperService.DoSomethingWithDonation(donation);
}

そこでは、あるサービスからデータ コントラクトを取得し、それをまったく無関係のサービスに送信したことがわかります。これは自然に見えます (クラス X のメソッドから返されるオブジェクトがあり、それを取得してクラスの引数として渡しました)。はい、プログラミングと同じように、仕事は終わりました)。

: この手法を使用しても、サービス参照が常に機能するのと同じように機能しなくなるわけではないため、既存のクライアント コードを変更する必要はありません。新しいラッパー サービスを使用する場合は、このように使用して型をマップする手間を省くことができます。

于 2012-04-06T08:23:08.637 に答える