XmlSerializer-タイプを反映するエラーがありました


332

C#.NET 2.0を使用して、[Serializable]属性を持つ複合データクラスがあります。私はXMLSerializerクラスを作成し、それをコンストラクタに渡します:

XmlSerializer serializer = new XmlSerializer(typeof(DataClass));

私は例外を言っています:

エラー反映タイプがありました。

データクラス内には、別の複合オブジェクトがあります。これには[Serializable]属性も必要ですか、または最上位のオブジェクトにそれを置くことにより、内部のすべてのオブジェクトに再帰的に適用されますか?

回答:


413

あなたが得ている内側の例外を見てください。シリアル化で問題が発生しているフィールド/プロパティがわかります。

[XmlIgnore]属性で装飾することにより、フィールド/プロパティをxmlシリアル化から除外できます。

XmlSerializer[Serializable]属性を使用しないので、それが問題だとは思いません。


11
オブジェクトにUriフィールドがあったため、この例外が発生しました。Uriクラスにはパラメーターのないコンストラクターがありません。先端をありがとう。
フォード

10
グーグル検索でこれに遭遇しました-私の特定の問題はIList、それが必要であるときのように、私の「直列化される」クラスにプロパティがあることでしたList
Paul Aldred-Bann

7
「内部例外」をどのように見ますか?
David

7
または時計に「@exception」を追加
arolson101

19
ありがとう、この答えは私を助けてくれました。私は最初に内部の例外を見ました、そしてちょうどメインクラスの言及を見ました。しかし、私は内部受容の内部例外にドリルダウンできることに気づき、最終的には5レベル下がると問題が見つかりました。相反する授業がありました。ありがとう。
Louis van Tonder 2013

111

シリアル化されたクラスには、デフォルト(つまり、パラメーターなし)コンストラクターが必要であることに注意してください。コンストラクタがない場合でも問題ありません。ただし、パラメーター付きのコンストラクターがある場合は、デフォルトのコンストラクターも追加する必要があります。


4
念押し有難う!これはほとんど説明のない実行時エラーだとは思いません。
Jared Updike、

私はこの間違いを何度も繰り返し続けています。パラメータなしのコンストラクタを使用するよう
通知していただきありがとうござい

25

同様の問題があり、シリアライザが同じ名前の2つのクラスを区別できないことがわかりました(一方は他方のサブクラスでした)。内部例外は次のようになります。

'Types BaseNamespace.Class1'および 'BaseNamespace.SubNamespace.Class1'は両方とも、ネームスペース ''からのXMLタイプ名 'Class1'を使用します。XML属性を使用して、型の一意のXML名または名前空間、あるいはその両方を指定します。

ここで、BaseNamespace.SubNamespace.Class1は、BaseNamespace.Class1のサブクラスです。

私がする必要があるのは、クラスの1つに属性を追加することです(基本クラスに追加しました)。

[XmlType("BaseNamespace.Class1")]

注:クラスのレイヤーが複数ある場合は、それらにも属性を追加する必要があります。


これで問題が解決しました。ありがとうございます、+ 1。複数のProcessor *オブジェクトを使用して同様の設定を行い、それぞれにConfig内部クラスを設定しました。ランタイムは、SomeNS.Processor1.ConfigとSomeNS.Processor2.Configを区別できませんでした。
damix911 2012年


6

私による最も一般的な理由:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members


5

特定の属性(つまり、ディクショナリ、または任意のクラス)を処理する必要がある場合は、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リフレクションを使用してカスタムクラスを実装するのは簡単です。


4

.Net 2.0のDictionaryクラスはXMLを使用してシリアル化できませんが、バイナリシリアル化を使用すると適切にシリアル化されることを発見しました。

ここで仕事を見つけました。


3

最近、新しいプロパティを追加するときに、これをWeb参照部分クラスで取得しました。自動生成されたクラスは、次の属性を追加していました。

    [System.Xml.Serialization.XmlElementAttribute(Order = XX)]

自動生成されたシーケンスの最後の属性よりも1つ高い次数を持つ同様の属性を追加する必要があり、これにより修正されました。


3

同じエラーが発生し、typeのプロパティにIEnumerable<SomeClass>問題があることがわかりました。その表示されIEnumerable、直接シリアライズすることはできません。

代わりに、を使用できますList<SomeClass>


2

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がパブリックプロパティに対してリフレクションを使用していると思います。


1

2つの要素の順序が同じである状況がありました

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]

....いくつかのコード...

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]

コードを変更して、クラスの新しいプロパティごとに1つずつ順序を増やすと、エラーは解消しました。


1

データ型-を持つプロパティを作成したときにも同じエラーが発生しましたType。これについて、エラーが発生しました-タイプを反映するエラーがありました。私はデバッグドックからのすべての例外の「InnerException」をチェックし続けType、私の場合は特定のフィールド名(これはでした)を取得しました。解決策は次のとおりです。

    [XmlIgnore]
    public Type Type { get; set; }

0

また、ユーザーインターフェイスコントロールをシリアル化することはできません。また、クリップボードに渡すオブジェクトはシリアル化可能でなければならないことに注意してください。そうしないと、他のプロセスに渡すことができません。



0

同じ問題があり、私の場合、オブジェクトにはReadOnlyCollectionがありました。コレクションがシリアル化可能になるには、Addメソッドを実装する必要があります。


これは質問に対する正しい答えではありません。この質問にはすでに15の回答があります。自分の答えが他の答えよりも優れていると思う場合は、それについてより詳細に説明する必要があります。いくつかのコードと出力スニペットを提供することは、常にユーザーに役立ちます。回答を投稿する前に、次を読むことを検討してください-> stackoverflow.com/help/how-to-answer
Amit Phaltankar

0

私はこれまでにここで説明したすべてに対して少し異なる解決策を持っているので、将来の文明のためにここにあります!

元の型がaだったので、「time」のデータ型を宣言し、TimeSpanその後に変更しましたString

[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]

しかし、実際のタイプは文字列でした

public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

DateTypeプロパティを削除することにより、Xmlシリアル化できます

[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

0
[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

または

[XmlIgnore]
string [] strFielsName {get;set;}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.