XmlSerializer - Có một loại phản ánh lỗi


332

Sử dụng C # .NET 2.0, tôi có một lớp dữ liệu tổng hợp có [Serializable]thuộc tính trên đó. Tôi đang tạo một XMLSerializerlớp và chuyển nó vào hàm tạo:

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

Tôi nhận được một ngoại lệ nói:

Có một loại phản ánh lỗi.

Bên trong lớp dữ liệu có một đối tượng tổng hợp khác. Điều này cũng cần phải có [Serializable]thuộc tính, hoặc bằng cách đặt nó trên đối tượng trên cùng, liệu nó có áp dụng đệ quy nó cho tất cả các đối tượng bên trong không?

Câu trả lời:


413

Nhìn vào ngoại lệ bên trong mà bạn đang nhận được. Nó sẽ cho bạn biết lĩnh vực / tài sản nào đang gặp sự cố nối tiếp.

Bạn có thể loại trừ các trường / thuộc tính khỏi xml serialization bằng cách trang trí chúng với [XmlIgnore]thuộc tính.

XmlSerializerkhông sử dụng [Serializable]thuộc tính, vì vậy tôi nghi ngờ đó là vấn đề.


11
Đối tượng của tôi có một trường Uri, gây ra ngoại lệ này; lớp Uri không có hàm tạo không tham số. Cảm ơn vì tiền hỗ trợ.
ford

10
Đã tìm ra điều này với một tìm kiếm google - vấn đề cụ thể của tôi là có một thuộc tính trong lớp "được nối tiếp" của tôi như IListkhi nó cần List.
Paul Aldred-Bann

7
Làm thế nào để một người nhìn vào một "ngoại lệ bên trong"?
David

7
hoặc thêm '@exception' vào đồng hồ
arolson101

19
Cảm ơn, câu trả lời này đã giúp tôi ra ngoài. Ban đầu tôi nhìn vào ngoại lệ bên trong, và chỉ thấy đề cập đến lớp chính. Nhưng tôi nhận ra rằng tôi có thể đi sâu vào những nhận thức vô căn cứ về những điều vô lý, và cuối cùng, giảm 5 cấp độ, tôi đã tìm ra vấn đề. Tôi đã có những lớp học xung đột. Cảm ơn.
Louis van Tonder

111

Hãy nhớ rằng các lớp được tuần tự hóa phải có các hàm tạo mặc định (tức là không tham số). Nếu bạn không có nhà xây dựng nào cả, điều đó tốt thôi; nhưng nếu bạn có một hàm tạo với một tham số, bạn cũng sẽ cần thêm một hàm mặc định.


4
Cảm ơn đã nhắc nhở! Tôi ghét rằng đây là một lỗi thời gian chạy với ít lời giải thích.
Jared Updike

Tôi cứ lặp đi lặp lại sai lầm này. cảm ơn vì đã nhắc tôi sử dụng một hàm tạo không tham số ^^
aZtraL-EnForceR

25

Tôi đã có một vấn đề tương tự, và hóa ra serializer không thể phân biệt giữa 2 lớp tôi có cùng tên (một lớp là lớp con của lớp kia). Ngoại lệ bên trong trông như thế này:

'Các loại BaseNamespace.Class1' và 'BaseNamespace.SubNamespace.Class1' đều sử dụng tên loại XML, 'Class1', từ không gian tên ''. Sử dụng các thuộc tính XML để chỉ định một tên và / hoặc không gian tên XML duy nhất cho loại.

Trong đó BaseNamespace.SubNamespace.Class1 là một lớp con của BaseNamespace.Class1.

Những gì tôi cần làm là thêm một thuộc tính cho một trong các lớp (tôi đã thêm vào lớp cơ sở):

[XmlType("BaseNamespace.Class1")]

Lưu ý: Nếu bạn có nhiều lớp lớp hơn, bạn cũng cần thêm một thuộc tính cho chúng.


Điều này đã khắc phục sự cố cho tôi, cảm ơn bạn, +1; Tôi đã có một cài đặt tương tự với một số đối tượng Bộ xử lý *, mỗi đối tượng có một lớp bên trong Cấu hình. Thời gian chạy không thể phân biệt giữa someNS.Processor1.Config và someNS.Processor2.Config.
damix911


6

Những lý do phổ biến nhất của tôi:

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


5

Nếu bạn cần xử lý các thuộc tính cụ thể (ví dụ: Từ điển hoặc bất kỳ lớp nào), bạn có thể triển khai giao diện IXmlSerialiable , điều này sẽ cho phép bạn tự do hơn với chi phí mã hóa dài hơn .

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
}

Có một bài viết thú vị , trong đó cho thấy một cách thanh lịch để thực hiện một cách tinh vi để "mở rộng" XmlSerializer.


Bài báo nói:

IXmlSerializable được đề cập trong tài liệu chính thức, nhưng tài liệu nói rằng nó không dành cho sử dụng công cộng và không cung cấp thông tin nào ngoài điều đó. Điều này chỉ ra rằng nhóm phát triển muốn bảo lưu quyền sửa đổi, vô hiệu hóa hoặc thậm chí loại bỏ hoàn toàn móc mở rộng này xuống đường. Tuy nhiên, miễn là bạn sẵn sàng chấp nhận sự không chắc chắn này và đối phó với những thay đổi có thể xảy ra trong tương lai, không có lý do gì bạn không thể tận dụng lợi thế của nó.

Bởi vì điều này, tôi đề nghị thực hiện IXmlSerializablecác lớp của riêng bạn , để tránh việc triển khai quá phức tạp.

... nó có thể đơn giản để thực hiện XmlSerializerlớp tùy chỉnh của chúng ta bằng cách sử dụng sự phản chiếu.


4

Tôi đã phát hiện ra rằng lớp Từ điển trong .Net 2.0 không được tuần tự hóa bằng XML, nhưng tuần tự hóa tốt khi sử dụng tuần tự hóa nhị phân.

Tôi tìm thấy một công việc xung quanh đây .


3

Gần đây tôi đã nhận được điều này trong một lớp tham chiếu web khi thêm một thuộc tính mới. Lớp được tạo tự động đã thêm các thuộc tính sau.

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

Tôi cần thêm một thuộc tính tương tự với thứ tự cao hơn thứ tự cuối cùng trong chuỗi được tạo tự động và điều này đã cố định nó cho tôi.


3

Tôi chỉ gặp lỗi tương tự và phát hiện ra rằng một thuộc tính loại IEnumerable<SomeClass>là vấn đề. Dường như IEnumerablekhông thể được nối tiếp trực tiếp.

Thay vào đó, người ta có thể sử dụng List<SomeClass>.


2

Tôi cũng nghĩ rằng thuộc tính Nối tiếp phải có trên đối tượng nhưng trừ khi tôi là một người mới hoàn thành (tôi đang ở giữa một phiên mã hóa đêm khuya), các công việc sau đây từ 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();
        }
    }

}

Tôi sẽ tưởng tượng rằng XmlSerializer đang sử dụng sự phản chiếu trên các thuộc tính công cộng.


1

Tôi đã có một tình huống mà Dòng giống nhau cho hai yếu tố liên tiếp

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

.... một số mã ...

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

Khi tôi thay đổi mã để tăng thứ tự một cho mỗi Thuộc tính mới trong lớp, lỗi sẽ biến mất.


1

Tôi đã nhận được cùng một lỗi khi tôi tạo một thuộc tính có kiểu dữ liệu - Type. Về điều này, tôi đã nhận được một lỗi - Có một loại phản ánh lỗi. Tôi tiếp tục kiểm tra 'InternalException' của mọi ngoại lệ từ dock gỡ lỗi và có tên trường cụ thể (đó là Type) trong trường hợp của tôi. Giải pháp như sau:

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

0

Cũng lưu ý rằng bạn không thể tuần tự hóa các điều khiển giao diện người dùng và bất kỳ đối tượng nào bạn muốn chuyển vào bảng tạm phải được tuần tự hóa nếu không nó không thể được chuyển qua các quy trình khác.



0

Tôi đã có cùng một vấn đề và trong trường hợp của tôi, đối tượng đã có ReadOnlyCollection. Một bộ sưu tập phải thực hiện phương thức Add để được tuần tự hóa.


Đây không phải là một câu trả lời thích hợp cho câu hỏi. Có 15 câu trả lời khác cho câu hỏi này. Nếu bạn nghĩ rằng câu trả lời của bạn tốt hơn những câu hỏi khác, bạn nên cung cấp thêm chi tiết về nó. Cung cấp một số đoạn mã & đầu ra luôn giúp người dùng. Trước khi đăng câu trả lời của bạn, hãy cân nhắc việc đọc -> stackoverflow.com/help/how-to-answer
Amit Phaltankar

0

Tôi có một giải pháp hơi khác với tất cả được mô tả ở đây cho đến nay, vì vậy đối với bất kỳ nền văn minh nào trong tương lai, đây là của tôi!

Tôi đã khai báo một kiểu dữ liệu về "thời gian" vì kiểu ban đầu là một TimeSpanvà sau đó đổi thành String:

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

tuy nhiên loại thực tế là một chuỗi

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

bằng cách loại bỏ DateTypetài sản Xmlcó thể được tuần tự hóa

[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)]

Hoặc là

[XmlIgnore]
string [] strFielsName {get;set;}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.