web-dev-qa-db-ja.com

KnownType属性を使用するのが適切な場合

MSDNリファレンスを読んだ後、KnownType属性をいつ使用するかについての質問があります。属性が型情報をシリアライザーに伝えることを理解していますが、これはいつ必要ですか?シリアル化されるクラスに基本クラス型の参照があり、それらの参照に設定できるアップキャスト派生クラスがある場合は適切ですか?

さらに、属性を使いすぎることには欠点がありますか?たとえば、前の例で、その型への明示的な参照があったとしても、シリアル化されたクラスがKnownType(baseClass)でマークされていた場合はどうでしょうか?

44
bwerks

[KnownType]は、サブタイプについて伝えるために必要です。 notを使用することの欠点は、以下が機能しないことです:

[DataContract]
class Foo {}

[DataContract]
class Bar : Foo {}

以下を返すWCFインターフェイスのメソッドを使用します。

public Foo GetFoo() { return new Bar(); }

属性がない場合、シリアライザ(特にmex/proxy-generatedタイプの場合)Barを知らないで、失敗します。属性付き:

[DataContract, KnownType(typeof(Bar))]
class Foo {}

itwillは機能します。これはDataContractSerializerにのみ適用されます-NetDataContractSerializerを使用すると、異なる方法で型データを取得できます。

66
Marc Gravell

スキーマでXSDの「継承」を使用している場合。

あなたはそれを逆に持っています。 KnownTypeAttributeは基本クラスに適用され、基本への参照として渡される可能性のあるすべての派生クラスに名前を付けます。

例えば:

...
KnownType(typeof(POBoxAddress))
KnownType(typeof(StreetAddress))
KnownType(typeof(SingleLineAddress))
KnownType(typeof(ParsedAddress))
public abstract class AddressBase
{
    ...
}
7
Toby

インターフェイスや基本クラスなどの非コンクリート型をシリアル化する場合は、KnownType属性が必要です。 WCFシリアライザーは、インターフェイスまたは継承されたクラスのすべての可能な実装について知っている必要があります。実装がわからない場合、シリアル化例外が発生します。

考えられる使用法の1つは、この中にあります SO question

6
chilltemp

以下のような場合にも役立ちます。

[DataContract]
[knownType(typeof(Person))]
public class KeyValue
{
  [DataMember]
  public string key {get; set;}

  [DataMember]
  public string value {get; set;}

  // rest of the code
}

ここで、値には、Personなどの他のクラスのオブジェクトが含まれているとします。これがすべて動作するには、knownType(typeof(Person))を追加する必要があります

0
Guruji