C#.NET 2.0を使用して、私は持っている複合データクラスを持っています[Serializable]
その上に属性。私は作成していますXMLSerializer
クラスとそれをコンストラクタに渡す:
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
私は例外を言っているのですが:
型を反映するエラーがありました。
データクラス内には、もう1つの複合オブジェクトがあります。これはまた持っている必要がありますか[Serializable]
属性、またはそれを一番上のオブジェクトに持つことで、それを内部のすべてのオブジェクトに再帰的に適用しますか。
あなたが得ている内部の例外を見てください。どのフィールド/プロパティがシリアル化に問題があるのかがわかります。
あなたはそれらをで飾ることによってxml直列化からフィールド/プロパティを除外することができます。[XmlIgnore]
属性。
私はそうは思わないXmlSerializer
を使用します[Serializable]
属性なので、それが問題ではないと思います。
直列化されたクラスにはデフォルトの(つまりパラメータのない)コンストラクタが必要です。あなたがまったくコンストラクタを持っていなければ、それで問題ありません。ただし、パラメータを持つコンストラクタがある場合は、デフォルトのものも追加する必要があります。
私は同じような問題を抱えていた、そしてそれはシリアライザが私が同じ名前を持っていた2つのクラスを区別することができなかったことがわかった(1つは他のサブクラスだった)。内部例外は次のようになりました。
'Types BaseNamespace.Class1'と 'BaseNamespace.SubNamespace.Class1'はどちらも、名前空間 ''からのXML型名 'Class1'を使用します。 XML属性を使用して、タイプに固有のXML名または名前空間、あるいはその両方を指定します。
BaseNamespace.SubNamespace.Class1はBaseNamespace.Class1のサブクラスです。
必要なのは、クラスの1つに属性を追加することです(私は基本クラスに追加しました)。
[XmlType("BaseNamespace.Class1")]
注:クラスの層がもっとある場合は、それらに属性を追加する必要があります。
私による最も一般的な理由:
- the object being serialized has no parameterless constructor
- the object contains Dictionary
- the object has some public Interface members
直列化グラフ内のすべてのオブジェクトは直列化可能でなければなりません。
からXMLSerializer
ブラックボックスです。シリアル化プロセスをさらにデバッグする場合は、これらのリンクを確認してください。
もしあなたが特定の属性(すなわち辞書、または任意のクラス)を扱う必要があるならば、あなたは以下を実装することができます。IXmlSerialiableより自由に使えるインターフェースより冗長なコーディングを犠牲にして。
public class NetService : IXmlSerializable
{
#region Data
public string Identifier = String.Empty;
public string Name = String.Empty;
public IPAddress Address = IPAddress.None;
public int Port = 7777;
#endregion
#region IXmlSerializable Implementation
public XmlSchema GetSchema() { return (null); }
public void ReadXml(XmlReader reader)
{
// Attributes
Identifier = reader[XML_IDENTIFIER];
if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
}
public void WriteXml(XmlWriter writer)
{
// Attributes
writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
}
private const string XML_IDENTIFIER = "Id";
private const string XML_NETWORK_ADDR = "Address";
private const string XML_NETWORK_PORT = "Port";
#endregion
}
おもしろい記事これは、XmlSerializerを「拡張する」洗練された方法を実装するためのエレガントな方法を示しています。
記事は言う:
IXmlSerializableは公式文書で扱われていますが、その文書には公的利用を意図したものではなく、それ以上の情報は提供されていません。これは、開発チームがこの拡張性フックを変更、無効化、さらには完全に削除する権利を留保することを望んでいたことを示しています。ただし、この不確実性を受け入れて将来の可能性のある変更に対処する意思がある限り、それを利用できない理由はありません。
これは、自分で実装することをお勧めします。IXmlSerializable
あまりにも複雑な実装を避けるためのクラス。
...私たちの習慣を実装するのは簡単かもしれませんXmlSerializer
リフレクションを使用したクラス
.NET 2.0のDictionaryクラスはXMLを使用してシリアライズすることはできませんが、バイナリシリアライゼーションを使用するとうまくシリアライズされます。
私は回避策を見つけましたここに。
私は最近、新しいプロパティを追加するときにWeb参照部分クラスでこれを得ました。自動生成されたクラスは以下の属性を追加していました。
[System.Xml.Serialization.XmlElementAttribute(Order = XX)]
私は自動生成されたシーケンスの最後のものより1つ上のオーダーで同様の属性を追加する必要があり、これは私のためにそれを修正しました。
私もSerializable属性をオブジェクトに含める必要があると考えましたが、私が完全な人でない限り(私は深夜のコーディングセッションの真ん中にいます)、次の作品をSnippetCompiler:
using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;
public class Inner
{
private string _AnotherStringProperty;
public string AnotherStringProperty
{
get { return _AnotherStringProperty; }
set { _AnotherStringProperty = value; }
}
}
public class DataClass
{
private string _StringProperty;
public string StringProperty
{
get { return _StringProperty; }
set{ _StringProperty = value; }
}
private Inner _InnerObject;
public Inner InnerObject
{
get { return _InnerObject; }
set { _InnerObject = value; }
}
}
public class MyClass
{
public static void Main()
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml");
DataClass clazz = new DataClass();
Inner inner = new Inner();
inner.AnotherStringProperty = "Foo2";
clazz.InnerObject = inner;
clazz.StringProperty = "foo";
serializer.Serialize(writer, clazz);
}
finally
{
Console.Write("Press any key to continue...");
Console.ReadKey();
}
}
}
私は、XmlSerializerがパブリックプロパティに対してリフレクションを使用していると思います。
私はちょうど同じエラーを得たとタイプのプロパティがIEnumerable<SomeClass>
問題でした。どうやらIEnumerable
直接シリアル化することはできません。
2つの要素が順番に並んでいるのにOrderが同じという状況がありました
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
....いくつかのコード...
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
クラス内の新しいPropertyごとに順番を1つ増やすようにコードを変更したところ、エラーは消えました。
また、ユーザーインターフェイスコントロールをシリアル化することはできません。また、クリップボードに渡すオブジェクトはシリアル化可能である必要があります。そうしないと他のプロセスに渡すことができません。
私は使っていますNetDataSerialiser
直列化するクラス
私のドメインクラスNetDataContractSerializerクラス。
ドメインクラスはクライアントとサーバー間で共有されます。
[System.Xml.Serialization.XmlElementAttribute( "strFieldName"、Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
//または
[XmlIgnore] string [] strFielsName {get; set;}
私は同じ問題を抱えていました、そして私のケースではオブジェクトはReadOnlyCollectionを持っていました。コレクションは、直列化可能にするためにAddメソッドを実装する必要があります。
IList
必要なときList
。 - Paul Aldred-Bann