355

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

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

次のような例外が発生します。

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

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

4

19 に答える 19

434

取得している内部例外を見てください。シリアル化に問題があるフィールド/プロパティが表示されます。

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

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

于 2008-09-13T14:53:09.820 に答える
114

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

于 2008-09-13T16:23:20.480 に答える
26

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

'Types BaseNamespace.Class1' と 'BaseNamespace.SubNamespace.Class1' は両方とも、名前空間 '' の XML 型名 'Class1' を使用します。XML 属性を使用して、型の一意の XML 名や名前空間を指定します。

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

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

[XmlType("BaseNamespace.Class1")]

注: クラスの層がさらにある場合は、それらにも属性を追加する必要があります。

于 2011-09-16T21:51:10.547 に答える
7

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

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members
于 2014-02-22T12:29:00.810 に答える
7

また、抽象プロパティをシリアル化できないことに注意してください。ここでXmlSerializer私の質問を参照してください(ソリューションコードを追加しました)。

XML シリアル化と継承された型

于 2008-09-13T17:31:05.900 に答える
5

同じエラーが発生し、タイプのプロパティがIEnumerable<SomeClass>問題であることがわかりました。IEnumerable直接シリアル化できないようです。

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

于 2012-01-12T12:59:07.013 に答える
5

シリアライゼーション グラフ内のすべてのオブジェクトは、シリアライズ可能である必要があります。

はブラックボックスであるためXMLSerializer、シリアライゼーション プロセスをさらにデバッグする場合は、これらのリンクを確認してください。

XmlSerializer が一時アセンブリを出力する場所を変更する

方法: .NET XmlSerializer で生成されたアセンブリにデバッグする

于 2008-09-13T15:05:24.223 に答える
5

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

于 2010-04-26T18:34:26.923 に答える
4

.Net 2.0 の Dictionary クラスは XML を使用してシリアライズできませんが、バイナリ シリアライズを使用するとうまくシリアライズされることがわかりました。

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

于 2009-07-02T19:32:19.697 に答える
3

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

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

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

于 2010-12-17T14:15:18.633 に答える
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 はパブリック プロパティに対してリフレクションを使用していると思います。

于 2008-09-13T15:23:04.103 に答える
1

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

    [XmlIgnore]
    public Type Type { get; set; }
于 2019-12-17T10:58:04.863 に答える
1

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

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

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

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

クラス内の新しいプロパティごとに順序を 1 ずつ増やすようにコードを変更すると、エラーはなくなりました。

于 2012-12-17T22:22:07.277 に答える
0

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

于 2008-09-13T14:55:17.693 に答える
0

このクラスを使用してNetDataSerialiser、ドメイン クラスをシリアル化しています。NetDataContractSerializer クラス.

ドメイン クラスは、クライアントとサーバー間で共有されます。

于 2008-09-16T13:14:18.520 に答える