web-dev-qa-db-ja.com

XMLシリアル化可能なクラスにパラメーターなしのコンストラクターが必要な理由

Xmlシリアル化を行うコードを書いています。以下の機能付き。

public static string SerializeToXml(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

引数がパラメーターなしのコンストラクターを持たないクラスのインスタンスである場合、例外をスローします。

未処理の例外:System.InvalidOperationException:CSharpConsole.Fooは、パラメーターなしのコンストラクターがないため、シリアル化できません。 System.Xml.Serialization.TypeDesc.CheckSupported()at System.Xml.Serialization.TypeScope.GetTypeDesc(Type type、MemberInfo sourc e、Boolean directReference、Boolean throwOnError)at System.Xml.Serialization.ModelScope.GetTypeModel(Type type、ブール直接参照)System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type、XmlRootAttribute root、String defaultNamespace)at System.Xml.Serialization.XmlSerializer..ctor(Type type、String defaultName space)at System.Xml.Serialization XmlSerializer..ctor(タイプタイプ)

XMLのシリアル化を成功させるために、パラメーターなしのコンストラクターが必要なのはなぜですか?

編集:cfedukeの答えをありがとう。パラメーターなしのコンストラクターは、プライベートまたは内部にすることができます。

167
Morgan Cheng

オブジェクトの逆シリアル化中に、オブジェクトの逆シリアル化を担当するクラスは、シリアル化されたクラスのインスタンスを作成し、移入するインスタンスを取得した後にのみ、シリアル化されたフィールドとプロパティを移入します。

必要に応じて、パラメータなしである限り、コンストラクタをprivateまたはinternalにすることができます。

234
cfeduke

これはXmlSerializerの制限です。 BinaryFormatterおよびDataContractSerializerdo notはこれを必要としないことに注意してください-エーテルから初期化されていないオブジェクトを作成し、逆シリアル化。

Xmlを使用しているので、DataContractSerializerを使用して[DataContract]/[DataMember]でクラスをマークすることを検討できますが、これによりスキーマが変更されることに注意してください(たとえば、[XmlAttribute]-すべてが要素になります)。

更新:本当に知りたい場合は、BinaryFormatterなどが FormatterServices.GetUninitializedObject() を使用して、コンストラクターを呼び出さずにオブジェクトを作成します。おそらく危険です。あまり頻繁に使用することはお勧めしません;-p MSDNの備考も参照してください。

オブジェクトの新しいインスタンスはゼロに初期化され、コンストラクターは実行されないため、オブジェクトはそのオブジェクトによって有効と見なされる状態を表さない場合があります。現在のメソッドは、ユーザーがすべてのフィールドにすぐにデータを入力する場合にのみ、逆シリアル化に使用する必要があります。不変型の空のインスタンスを作成しても意味がないため、初期化されていない文字列は作成されません。

own シリアル化エンジンがありますが、FormatterServicesを使用するつもりはありません。コンストラクター(anyコンストラクター)が実際に実行されたことを知っているのはとても好きです。

73
Marc Gravell

まず第一に、これは documentation で書かれています。私はそれがあなたのクラスフィールドの1つであり、メインのものではないと思う-そして、どのようにデシリアライザがパラメータなしの構築なしでそれを構築するか?

コンストラクタをプライベートにするための回避策があると思います。

0
Dmitry Khalatov