2012-02-09 20 views
2

何百ものプロパティを持つ約50クラスのC#クラスライブラリがあります。クラスをインスタンス化するにはしばらく時間がかかることがあります。最適化のために、サーバー上でインスタンス化し、インスタンス化されたクラスをWCFサービス経由でクライアントアプリケーションに渡すことを検討していました。WCFサービスを使用してインスタンス化されたクラスを渡す

正常に動作しているようです。しかし、私が理解しているところから、私がこれをやりたいのであれば、すべてのクラスに[DataContract]とマークするだけでなく、すべてのプロパティを[DataMember]とマークする必要があります。これは本当に本当ですか?これは、特にすべてのプロパティで行う必要があることを夢中に思えます。このプロセスを進むことなく、クラス全体が直列化可能であると言うだけの方法はありますか?

答えて

3

[DataContract]を使用する場合は、メンバーごとに[DataMember]を指定する必要があります。また

から[Serializable]を持つクラスをマークし、あなたが明示的に(オプトインアプローチに関する[DataContract]作品に対し、オプトアウトのアプローチに[Serializable]作品)そう言わない限り、シリアライザは、あなたのためのすべての内部をシリアル化します。

しかし、正確に何をしようとしているかによって、この方法には欠陥がある可能性があります。

WCFでオブジェクトを渡すと、実際にオブジェクトを渡すことは全くありません。オブジェクトのコピーを渡していることになります。実際、元のオブジェクトはシリアル化され、ワイヤを通され、反対側で逆シリアル化されます。つまり、クライアントはまだインスタンス化をインスタンス化し、クラスのインスタンスを再構成してからすべてのプロパティを設定します。何も得られず、潜在的にかなりの費用がかけられ、多くのデータが配線を通過します。

それはすべてあなたが何をしているかによって異なります。インスタンスのコピーを取得しているクライアントが気にしなくても、費用がデータ量のせいではなく、データベースへのアクセスが遅いなどの理由がある場合は、問題ありません。さもなければあなたのアプローチはあなたに何も買わないかもしれない。

脇に、ネットリモーティングはリモートオブジェクトへの参照を持つことができます(つまり、クライアントはサーバー上のオブジェクトを参照できます)。タイプ自体がMarshalByRefObjectから派生していますが、WCFの場合はそうではありません。ローカルにコピーします。

+0

あなたは間違っていません - OPはおそらくパフォーマンスの方法で何かを得ることはないでしょう。しかし、これは実際に、直列化の属性を持つクラスとプロパティを装飾することについての彼の質問にはあてはまらない。 – Yuck

+0

@Yuckは真実ですが、作成することは非常に重要なポイントです。 – kenny

+0

待って...それは正しいように見えません。したがって、クライアントアプリケーションに次のコードがあると、オブジェクトのコンストラクタがWCFサーバーだけでなくクライアントマシンにも呼び出されるということです。クライアントマシンはコンストラクタを2度目に呼び出さずにインスタンス化されたコピーを取得するはずです。MyObject obj = null; static void WCF_SVC_GetMyObjInstCompleted(オブジェクト送信者、WCF_SVCRef.GetMyObjInstCompletedEventArgs){obj = e.Result; } – Nullqwerty

2

私がこれを行う場合は、すべてのクラスを[DataContract] とマークするだけでなく、すべてのプロパティを[DataMember]としてマークする必要があります。これは本当に ですか?

はい、いいえ。

クライアントコードがこれらのクラスを含むアセンブリをインポートできない場合は、それらをマークアップする必要があります。これは、WCFがクライアントに結果セットの解釈方法を伝えることができるようにするためです。

WCFサービスの両方で共通のアセンブリを使用することができます(POCOライブラリなど)。これらの属性を適用する必要はありません。 WCFは、厳密な名前でアセンブリを参照するようにクライアントに指示します。

はここでWSDLがケース#2にどのように見えるかです:

MyAssembly.MyProjectは、上記のあなたのアセンブリ内の名前空間を参照し
<wsdl:types> 
    <xsd:schema targetNamespace = "http://tempuri.org/Imports"> 
    <xsd:import schemaLocation = "http://localhost:12902/MyService.svc?xsd=xsd0" 
     namespace="http://tempuri.org/" /> 
    <xsd:import schemaLocation = "http://localhost:12902/MyService.svc?xsd=xsd1" 
     namespace="http://schemas.microsoft.com/2003/10/Serialization/" /> 
    <xsd:import schemaLocation = "http://localhost:12902/MyService.svc?xsd=xsd2" 
     namespace="http://schemas.datacontract.org/2004/07/MyAssembly.MyProject" /> 
    </xsd:schema> 
</wsdl:types> 

http://localhost:12902/MyService.svc?xsd=xsd2(ローカルマシン上)のリンクをたどると、その名前空間内でシリアライズされたエンティティを表すXSDが表示されます。あなたはクラスを飾る必要はありません。 WCFはこれをあなたのためにすべて行います。

+0

これはあなたが言っていることですか?私はdllを生成するクラスライブラリを持っています。私は、クライアントアプリケーションのプロジェクトにdllを含め、wcfサービスのプロジェクトにdllを含めます。これを行うと、クラスライブラリのクラスでdatacontractまたはdatamemberのいずれかをマークする必要はありませんが、wcfサービスを介してインスタンス化クラスを渡すことはできますか? – Nullqwerty

+0

@Nullqwertyそれは正しいです。しかし、いくつかの制限があります。明らかにする必要がありますが、このアプローチは、Visual Studioを使用してサービス参照をインポートするときに.NETが提供する自動生成クライアントクラスでのみ機能します。サービスを消費する以外のものがあれば、クラスを属性で装飾するアプローチを使用する必要があります。私の答えを更新します... – Yuck

+0

"このアプローチは、Visual Studioを使用してサービス参照をインポートすると.NETが提供する自動生成されたクライアントクラスでのみ機能します。" ....ああ、それは意味があります。実際にこれを最初に試してみましたが、サービスコールでエラーが発生しました。しかし、私が使用していたクライアントオブジェクトは、クラスライブラリからのタイプのものであり、自動生成されたクラスからのものではありませんでした。興味深い...クライアントアプリケーションはすでに成熟した製品であり、かなり大きいので、変更する必要があるため、このアプローチの意義について考える必要があります。助けてくれてありがとう! – Nullqwerty

0

基本的にはyesです。 NETがそれらのクラスを直列化することを知るためには、クラス、構造体、フィールドに2つのプロパティが必要です。これらのプロパティがなければ、それらはシリアル化されず、クライアントのフィールドやクラスは表示されません。

0

本当に別のクライアントサーバーシナリオでは、 (ファイルを共有できない場合)

関連する問題