XmlSerializer クラスの使用
クライアント (DataContractSerializer
) とサービス (XmlSerializer
) の間で転送されるアプリケーションのデータを XML に変換するために、Windows Communication Foundation (WCF) では 2 つの異なるシリアル化テクノロジを使用できます。
DataContractSerializer
データ型をシリアル化するために WCF によって既定で使用されるのは、DataContractSerializer クラスです。 このシリアライザーは、次の型をサポートします。
プリミティブ型 (整数、文字列、バイト配列など) や、プリミティブとして処理される XmlElement や DateTime などの特殊な型。
データ コントラクト型 (DataContractAttribute 属性でマークされた型)。
SerializableAttribute インターフェイスを実装する型など、ISerializable 属性でマークされた型。
IXmlSerializable インターフェイスを実装する型。
多くのジェネリック コレクション型を含む多くの共通コレクション型。
多くの .NET Framework 型は、下の 2 つのカテゴリに分類され、したがってシリアル化可能です。 シリアル化可能な型の配列もシリアル化可能です。 完全な一覧については、「サービス コントラクトでのデータ転送の指定」を参照してください。
新しい WCF サービスを記述する方法としては、DataContractSerializer をデータ コントラクト型と共に使用することが推奨されます。 詳細については、「データ コントラクトの使用」を参照してください。
XmlSerializer
WCF では XmlSerializer クラスもサポートされています。 XmlSerializer クラスは、WCF に固有のものではありません。 これは、ASP.NET Web サービスによって使用されるものと同じシリアル化エンジンです。 XmlSerializer クラスでは、DataContractSerializer クラスよりもサポートされる型の範囲がずっと狭くなりますが、結果の XML に対する制御の柔軟性に優れています。また、XML スキーマ定義言語 (XSD) 標準のサポート範囲が広く、 シリアル化可能な型で宣言型属性が要求されません。 詳細については、.NET Framework のドキュメントの XML シリアル化に関するトピックを参照してください。 XmlSerializer クラスは、データ コントラクト型をサポートしません。
サードパーティ サービス用のクライアント コードを生成したり、サードパーティのスキーマにアクセスしたりするために、Visual Studio の Svcutil.exe またはサービス参照の追加機能を使用すると、適切なシリアライザーが自動的に選択されます。 スキーマに DataContractSerializer との互換性がない場合は、XmlSerializer が選択されます。
XmlSerializer に切り替える
XmlSerializer に手動で切り替える必要が生じる場合もあります。 たとえば、次のような場合です。
アプリケーションを ASP.NET Web サービスから WCF に移行するときに、新しいデータ コントラクト型を作成するのではなく、既存の XmlSerializer 互換の型を再利用する場合。
メッセージに表示する XML に対する正確な制御が必要で、Web サービス記述言語 (WSDL) ドキュメントが利用できない場合。たとえば、DataContractSerializer と互換性がなく、標準化および公開されている特定のスキーマに従う必要のある型を使用して、サービスを作成する場合。
従来の SOAP エンコード標準に従うサービスを作成する場合。
上記を含めた多様な状況で、次のコードに示すように、XmlSerializer 属性をサービスに適用することにより、XmlSerializerFormatAttribute
クラスに手動で切り替えることができます。
[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
[OperationContract]
public void ProcessTransaction(BankingTransaction bt)
{
// Code not shown.
}
}
//BankingTransaction is not a data contract class,
//but is an XmlSerializer-compatible class instead.
public class BankingTransaction
{
[XmlAttribute]
public string Operation;
[XmlElement]
public Account fromAccount;
[XmlElement]
public Account toAccount;
[XmlElement]
public int amount;
}
//Notice that the Account class must also be XmlSerializer-compatible.
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
<OperationContract()> _
Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
' Code not shown.
End Sub
End Class
' BankingTransaction is not a data contract class,
' but is an XmlSerializer-compatible class instead.
Public Class BankingTransaction
<XmlAttribute()> _
Public Operation As String
<XmlElement()> _
Public fromAccount As Account
<XmlElement()> _
Public toAccount As Account
<XmlElement()> _
Public amount As Integer
End Class
'Notice that the Account class must also be XmlSerializer-compatible.
セキュリティに関する考慮事項
Note
シリアル化エンジンを切り替える場合は注意が必要です。 同じ型でも、使用するシリアライザーによって XML へのシリアル化方法が異なる場合があります。 誤って、不適切なシリアライザーを使用すると、公開する意図のない型の情報が公開されるおそれがあります。
たとえば、DataContractSerializer クラスは、データ コントラクト型をシリアル化する場合、DataMemberAttribute 属性でマークされたメンバーのみをシリアル化します。 XmlSerializer クラスは、すべてのパブリック メンバーをシリアル化します。 たとえば、次のコードの型を見てください。
[DataContract]
public class Customer
{
[DataMember]
public string firstName;
[DataMember]
public string lastName;
public string creditCardNumber;
}
<DataContract()> _
Public Class Customer
<DataMember()> _
Public firstName As String
<DataMember()> _
Public lastName As String
Public creditCardNumber As String
End Class
XmlSerializer クラスが選択されているサービス コントラクトでこの型が誤って使用された場合、意図したものではなくても creditCardNumber
メンバーがシリアル化されます。
DataContractSerializer クラスが既定の場合でも、DataContractFormatAttribute 属性をサービス コントラクト型に適用することで、このクラスをサービスに対して明示的に選択できます (ただし、この操作が必要になることはありません)。
サービスで使用するシリアライザーはコントラクトにとって不可欠な部分です。別のバインディングを選択しても他の構成設定に変更しても、このシリアライザーを変更することはできません。
XmlSerializer クラスについては、セキュリティに関する重要な考慮事項が他にもあります。 まず、XmlSerializer クラスを使用するすべての WCF アプリケーションには、情報の漏えいから保護されたキーを使って署名することを強くお勧めします。 このことは、XmlSerializer に手動で切り替える場合と、自動切り替えが行われる場合 (Svcutil.exe やサービス参照の追加などのツールによる) の両方でお勧めします。 これは、XmlSerializer シリアル化エンジンで "事前生成済みのシリアル化アセンブリ" の読み込みがサポートされるのは、それらがアプリケーションと同じキーで署名されている場合だけであるためです。 署名されていないアプリケーションは、アプリケーション フォルダーやグローバル アセンブリ キャッシュに配置される事前生成済みのシリアル化アセンブリで予想される名前に、悪意のあるアセンブリが一致するという危険性に対して完全に無防備になります。 もちろん、攻撃者がこのようなアクションを行うには、この 2 つの場所のいずれかに対する書き込みアクセスをまず取得する必要があります。
XmlSerializer を使用するときに必ず存在するもう 1 つの脅威は、システムの一時フォルダーへの書き込みアクセスに関連するものです。 XmlSerializer シリアル化エンジンにより、このフォルダー内に一時的な "シリアル化アセンブリ" が作成されて使用されます。 一時フォルダーへの書き込みアクセスのあるプロセスであれば、悪意のあるコードによってこれらのシリアル化アセンブリが上書きされるおそれがあることに注意してください。
XmlSerializer サポートのルール
XmlSerializer 互換の属性は、コントラクト操作のパラメーターまたは戻り値に直接適用できません。 ただし、次のコードに示すように、型指定されたメッセージ (メッセージ コントラクトの本文) には適用できます。
[ServiceContract]
[XmlSerializerFormat]
public class BankingService
{
[OperationContract]
public void ProcessTransaction(BankingTransaction bt)
{
//Code not shown.
}
}
[MessageContract]
public class BankingTransaction
{
[MessageHeader]
public string Operation;
[XmlElement, MessageBodyMember]
public Account fromAccount;
[XmlElement, MessageBodyMember]
public Account toAccount;
[XmlAttribute, MessageBodyMember]
public int amount;
}
<ServiceContract(), XmlSerializerFormat()> _
Public Class BankingService
<OperationContract()> _
Public Sub ProcessTransaction(ByVal bt As BankingTransaction)
'Code not shown.
End Sub
End Class
<MessageContract()> _
Public Class BankingTransaction
<MessageHeader()> _
Public Operation As String
<XmlElement(), MessageBodyMember()> _
Public fromAccount As Account
<XmlElement(), MessageBodyMember()> _
Public toAccount As Account
<XmlAttribute(), MessageBodyMember()> _
Public amount As Integer
End Class
型指定されたメッセージのメンバーに適用する場合、型指定されたメッセージ属性で競合するプロパティは、この属性によりオーバーライドされます。 たとえば、次のコードの ElementName
は、Name
をオーバーライドします。
[MessageContract]
public class BankingTransaction
{
[MessageHeader] public string Operation;
//This element will be <fromAcct> and not <from>:
[XmlElement(ElementName="fromAcct"), MessageBodyMember(Name="from")]
public Account fromAccount;
[XmlElement, MessageBodyMember]
public Account toAccount;
[XmlAttribute, MessageBodyMember]
public int amount;
}
<MessageContract()> _
Public Class BankingTransaction
<MessageHeader()> _
Public Operation As String
'This element will be <fromAcct> and not <from>:
<XmlElement(ElementName:="fromAcct"), _
MessageBodyMember(Name:="from")> _
Public fromAccount As Account
<XmlElement(), MessageBodyMember()> _
Public toAccount As Account
<XmlAttribute(), MessageBodyMember()> _
Public amount As Integer
End Class
MessageHeaderArrayAttribute の使用時は、XmlSerializer 属性はサポートされません。
Note
この場合、WCF より前にリリースされた XmlSerializer によって、"スキーマのトップ レベルで宣言された要素に maxOccurs
> 1 の値を含めることはできません。 XmlArray
ではなく、XmlArrayItem
または XmlElementAttribute
を使うか、Wrapped パラメーター スタイルを使って 'more' のラッパー要素を指定してください。" という例外がスローされます。
この例外が出力された場合は、この状況が当てはまるかどうかを調査します。
WCF では、メッセージ コントラクトおよび操作コントラクトでの SoapIncludeAttribute および XmlIncludeAttribute 属性はサポートされていません。代わりに、KnownTypeAttribute 属性を使用してください。
IXmlSerializable インターフェイスを実装する型
IXmlSerializable
インターフェイスを実装する型は、DataContractSerializer
で完全にサポートされます。 これらの型には、スキーマを制御するために必ず XmlSchemaProviderAttribute 属性を適用する必要があります。
警告
ポリモーフィック型をシリアル化する場合、XmlSchemaProviderAttribute を型に適用して、正しい型がシリアル化されるようにする必要があります。
IXmlSerializable
を実装する型には、任意のコンテンツを表す型、1 つの要素を表す型、および従来の DataSet 型の 3 種類があります。
コンテンツ型では、
XmlSchemaProviderAttribute
属性によって指定されたスキーマ プロバイダー メソッドが使用されます。 このメソッドからnull
が返されることはなく、属性の IsAny プロパティは既定値false
のままになります。 これは、IXmlSerializable
型の最も一般的な使用方法です。要素型は、
IXmlSerializable
型が自身のルート要素名を制御する必要があるときに使用します。 型を要素型としてマークするには、IsAny 属性の XmlSchemaProviderAttribute プロパティをtrue
に設定するか、スキーマ プロバイダー メソッドからnull
を返します。 スキーマ プロバイダー メソッドの使用は、要素型ではオプションです。null
でメソッド名の代わりにXmlSchemaProviderAttribute
を指定できます。 ただし、IsAny
がtrue
で、スキーマ プロバイダー メソッドが指定されている場合、メソッドはnull
を返す必要があります。従来の DataSet 型は、
IXmlSerializable
属性でマークされていないXmlSchemaProviderAttribute
型です。 これらの型は、スキーマ生成に関して GetSchema メソッドに依存しています。 以前のバージョンの .NET Framework では、このパターンがDataSet
型に使用され、型指定されたデータセットからクラスが派生されます。ただし、現在、このパターンは使用されなくなっており、従来の型に対応することだけを目的としてサポートされています。 このパターンに依存せず、必ずXmlSchemaProviderAttribute
をIXmlSerializable
型に適用してください。
IXmlSerializable コンテンツ型
IXmlSerializable
を実装しており、以前に定義したコンテンツ型である型のデータ メンバーをシリアル化すると、シリアライザーはそのデータ メンバーのラッパー要素を書き込み、WriteXml メソッドに制御を渡します。 WriteXml 実装により、ラッパー要素に属性が追加されるなど、任意の XML が書き込まれることがあります。 WriteXml
の実行後、シリアライザーは要素を閉じます。
IXmlSerializable
を実装しており、以前に定義したコンテンツ型である型のデータ メンバーを逆シリアル化すると、デシリアライザーはそのデータ メンバーのラッパー要素に XML リーダーを配置し、ReadXml メソッドに制御を渡します。 このメソッドは、開始タグと終了タグを含む、要素全体を読み取る必要があります。 ReadXml
コードでは、要素が空の場合も忘れずに処理してください。 また、ReadXml
の実装では、特定の方法で名前が付けられたラッパー要素に依存しないようにしてください。 シリアライザーによって選択される名前は、異なる場合があります。
IXmlSerializable
コンテンツ型は、たとえば Object 型のデータ メンバーなどに、ポリモーフィックに割り当てることができます。 また、型インスタンスを null にすることもできます。 さらに、IXmlSerializable
型は、オブジェクト グラフの保存を有効にして NetDataContractSerializer で使用することも可能です。 これらのすべての機能を実現するには、WCF シリアライザーが特定の属性 (XML スキーマ インスタンス名前空間の "nil" と "type"、WCF 固有の名前空間の "Id"、"Ref"、"Type"、および "Assembly") をラッパー要素に追加する必要があります。
ReadXml を実装するときに無視する属性
ReadXml
コードに制御を渡す前に、デシリアライザーは、XML 要素を調べ、前述の特別な XML 属性を検出し、その属性に従って動作します。 たとえば、"nil" が true
の場合は、null 値が逆シリアル化され、ReadXml
は呼び出されません。 ポリモーフィズムが検出された場合は、要素のコンテンツが別の型と同様に逆シリアル化されます。 ポリモーフィックに割り当てられた型の ReadXml
実装が呼び出されます。 どの場合も、これらの特別な属性がデシリアライザーによって処理されるため、ReadXml
実装ではこれらの属性を無視する必要があります。
IXmlSerializable コンテンツ型のスキーマに関する考慮事項
スキーマと IXmlSerializable
コンテンツ型をエクスポートすると、スキーマ プロバイダー メソッドが呼び出されます。 このスキーマ プロバイダー メソッドには、XmlSchemaSet が渡されます。 このメソッドは、有効なスキーマをスキーマ セットに追加できます。 スキーマ セットには、スキーマをエクスポートした時点で既に認識されていたスキーマが格納されます。 スキーマ プロバイダー メソッドは、スキーマ セットに項目を追加する必要があるときに、適切な名前空間を持つ XmlSchema がそのセットに既に存在するかどうかを確認する必要があります。 存在する場合、スキーマ プロバイダー メソッドは新しい項目を既存の XmlSchema
に追加する必要があります。 存在しない場合、新しい XmlSchema
インスタンスを作成する必要があります。 これは、IXmlSerializable
型の配列を使用する場合に重要です。 たとえば、IXmlSerializable
型を名前空間 "B" の "A" 型としてエクスポートする場合、スキーマ プロバイダー メソッドが呼び出される前に、"B" が "ArrayOfA" 型を保持するためのスキーマがスキーマ セットに既に存在している可能性があります。
型を XmlSchemaSet に追加する以外に、コンテンツ型のスキーマ プロバイダー メソッドは null 以外の値を返す必要があります。 このメソッドは、特定の XmlQualifiedName 型で使用するスキーマ型の名前を指定する IXmlSerializable
を返すことができます。 この修飾名は、その型のデータ コントラクト名および名前空間としても使用されます。 スキーマ プロバイダー メソッドは、スキーマ セットにまだ存在していない型であっても、復帰時に返すことができます。 ただし、関連するすべての型がエクスポートされる (Export の関連するすべての型に対して XsdDataContractExporter メソッドが呼び出され、Schemas プロパティにアクセスする) までに、その型がスキーマ セットに存在している必要があります。 関連するすべての Schemas
呼び出しが実行される前に Export
プロパティにアクセスすると、XmlSchemaException が発生する可能性があります。 エクスポート プロセスの詳細については、「クラスからのスキーマのエクスポート」を参照してください。
スキーマ プロバイダー メソッドは、使用する XmlSchemaType を返すこともできます。 その型は、匿名の場合とそうでない場合があります。 匿名の場合、IXmlSerializable
型のスキーマは、IXmlSerializable
型がデータ メンバーとして使用されるたびに匿名型としてエクスポートされます。 IXmlSerializable
型には、データ コントラクト名と名前空間が引き続き保持されます (これは、「データ コントラクト名」で説明されているとおりに決定されます。ただし、DataContractAttribute 属性を使用して名前をカスタマイズすることはできません)。匿名でない場合は、XmlSchemaSet
に含まれる型のいずれかである必要があります。 これは、型の XmlQualifiedName
を返す場合と同じです。
さらに、型のグローバル要素宣言がエクスポートされます。 型に XmlRootAttribute 属性が適用されていない場合、その要素にはデータ コントラクトと同じ名前と名前空間が使用され、その "nillable" プロパティは true
に設定されます。 唯一の例外は、スキーマ名前空間 (http://www.w3.org/2001/XMLSchema
) です。型のデータ コントラクトがこの名前空間にある場合は、新しい要素をスキーマ名前空間に追加することが禁止されているため、対応するグローバル要素は、空白の名前空間に属することになります。 型に XmlRootAttribute
属性が適用されている場合、グローバル要素宣言は、ElementName、Namespace、および IsNullable の各プロパティを使用してエクスポートされます。 XmlRootAttribute
が適用された場合の既定値は、データ コントラクト名、空白の名前空間、および true
に設定された "nillable" です。
同じグローバル要素宣言の規則が、従来のデータセット型に適用されます。 XmlRootAttribute
は、カスタム コードによって追加されたグローバル要素宣言をオーバーライドできません。これには、スキーマ プロバイダー メソッドを使用して XmlSchemaSet
に追加された場合と、従来のデータセット型に対して GetSchema
を使用して追加された場合があります。
IXmlSerializable 要素型
IXmlSerializable
要素型には、IsAny
に設定された true
プロパティか、null
を返すスキーマ プロバイダー メソッドのいずれかが含まれています。
要素型のシリアル化と逆シリアル化は、コンテンツ型のシリアル化と逆シリアル化に非常に似ています。 ただし、重要な違いがいくつかあります。
WriteXml
の実装では、要素 (これには複数の子要素が含まれている可能性もありますが) を 1 つだけ出力することが想定されています。 この 1 つの要素の外側にある属性、複数の兄弟要素、またはこれらが混在したコンテンツを出力することはできません。 要素は空であってもかまいません。ReadXml
の実装では、ラッパー要素の読み取りは想定されていません。 読み取ることが想定されているのは、WriteXml
で生成される要素 1 つのみです。要素型を一様にシリアル化する場合 (データ コントラクトのデータ メンバーとしてシリアル化する場合など) は、コンテンツ型の場合と同様に、
WriteXml
を呼び出す前にラッパー要素が出力されます。 ただし、WriteXml
コンストラクターまたはDataContractSerializer
コンストラクターによるシリアライザーの構築時にルート名と名前空間を明示的に指定しない限り、トップ レベルで要素型をシリアル化しても、通常はNetDataContractSerializer
で書き出される要素を囲むラッパー要素が出力されることはありません。 詳細については、「シリアル化と逆シリアル化」を参照してください。構築時にルート名と名前空間を指定せずにトップ レベルで要素型をシリアル化した場合、WriteStartObject と WriteEndObject では基本的に何も実行されず、WriteObjectContent によって
WriteXml
が呼び出されます。 このモードでは、シリアル化されるオブジェクトはnull
にできず、ポリモーフィックに割り当てることができません。 また、オブジェクト グラフの保存を有効化できず、NetDataContractSerializer
も使用できません。構築時にルート名と名前空間を指定せずにトップ レベルで要素型を逆シリアル化したときに、要素の先頭を検出できた場合は、IsStartObject が
true
を返します。 ReadObject パラメーターがverifyObjectName
に設定されているtrue
は、実際にオブジェクトを読み取る前の動作がIsStartObject
と同様です。 その後、ReadObject
は制御をReadXml
メソッドに渡します。
要素型の場合も、エクスポートされるスキーマは、前のセクションで説明した XmlElement
型に対するスキーマと同じです。ただし、スキーマ プロバイダー メソッドは、コンテンツ型と同様、追加のスキーマを XmlSchemaSet に追加できます。 要素型には XmlRootAttribute
属性を使用することはできないので、グローバル要素宣言は要素型に対して出力されません。
XmlSerializer との相違点
IXmlSerializable
インターフェイス、XmlSchemaProviderAttribute
属性、および XmlRootAttribute
属性は、XmlSerializer でも認識されます。 ただし、データ コントラクト モデルでの処理方法に違いがあります。 重要な違いを以下にまとめます。
スキーマ プロバイダー メソッドは、
XmlSerializer
で使用できるようにするためにパブリックにする必要がありますが、データ コントラクト モデルで使用するためにパブリックにする必要はありません。スキーマ プロバイダー メソッドは、データ コントラクト モデルで
IsAny
がtrue
の場合に呼び出されますが、XmlSerializer
では呼び出されません。コンテンツ型または従来のデータセット型に
XmlRootAttribute
属性がない場合、XmlSerializer
は、グローバル要素宣言を空白の名前空間にエクスポートします。 データ コントラクト モデルで通常使用される名前空間は、前に説明したとおりデータ コントラクトの名前空間です。
両方のシリアル化技術で使用する型を作成する場合には、これらの違いに注意してください。
IXmlSerializable スキーマのインポート
IXmlSerializable
型から生成されたスキーマをインポートする場合、次のような状況が考えられます。
生成されるスキーマは、「データ コントラクト スキーマの参照」で説明されているように、有効なデータ コントラクト スキーマである場合があります。 この場合は、スキーマを通常どおりにインポートでき、通常のデータ コントラクト型が生成されます。
生成されたスキーマが、有効なデータ コントラクト スキーマではない場合があります。 たとえば、スキーマ プロバイダー メソッドによって、データ コントラクト モデルでサポートされていない XML 属性を含むスキーマが生成されることがあります。 この場合、スキーマを
IXmlSerializable
型としてインポートできます。 このインポート モードは、既定では有効になっていませんが、たとえば ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) で/importXmlTypes
コマンド ライン スイッチを使用して、簡単に有効にすることができます。 これについての詳細は、「クラスを生成するためのスキーマのインポート」で説明しています。 型インスタンスを処理するには、XML を直接操作する必要があります。XmlSerializer
の使用方法に関するトピックを参照し、より広い範囲のスキーマをサポートする別のシリアル化技術を使用することを検討することもできます。新しい型を生成する代わりに、プロキシ内の既存の
IXmlSerializable
型を再利用できます。 この場合、「型を作成するためのスキーマのインポート」で説明する参照型の機能を使用して、再利用する型を示すことができます。 これは、Svcutil.exe で/reference
スイッチを使用して、再利用する型を含むアセンブリを指定することに相当します。
XmlSerializer の従来の動作
.NET Framework 4.0 以前では、XmlSerializer が C# コードをファイルに書き込むことによって、一時的なシリアル化アセンブリが生成されます。 さらに、このファイルがアセンブリとしてコンパイルされます。 この動作では、シリアライザーの起動時間が長くなるなど、望ましくない結果が生じることがあります。 .NET Framework 4.5 では、この動作が変更され、コンパイラを使用せずに、アセンブリが生成されるようになりました。 開発者によっては、生成された C# コードを確認したい場合もあります。 次の構成によって、この従来の動作を使用するように指定できます。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.xml.serialization>
<xmlSerializer tempFilesLocation='e:\temp\XmlSerializerBug' useLegacySerializerGeneration="true" />
</system.xml.serialization>
<system.diagnostics>
<switches>
<add name="XmlSerialization.Compilation" value="1" />
</switches>
</system.diagnostics>
</configuration>
非パブリックの新しいオーバーライドを含む派生クラスを XmlSerializer
でシリアル化できないといった、互換性に関する問題が発生する場合は、次の構成を使用することで、XMLSerializer
を従来の動作に戻すことができます。
<configuration>
<appSettings>
<add key="System:Xml:Serialization:UseLegacySerializerGeneration" value="true" />
</appSettings>
</configuration>
.NET Framework 4.5 以降のバージョンが実行されているコンピューターの場合、上記の構成の代わりに、次の構成を使用することもできます。
<configuration>
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true"/>
</system.xml.serialization>
</configuration>
Note
<xmlSerializer useLegacySerializerGeneration="true"/>
スイッチは、.NET Framework 4.5 以降のバージョンが実行されているコンピューターでのみ機能します。 上記の appSettings
の方法は、.NET Framework のすべてのバージョンで動作します。