XmlSerializer - Türü yansıtan bir hata oluştu


332

C # .NET 2.0 kullanarak, [Serializable]üzerinde özniteliği olan bir bileşik veri sınıfı var . Bir XMLSerializersınıf oluşturuyorum ve bunu yapıcıya geçiriyorum:

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

Bir istisna alıyorum:

Tür yansıtılırken bir hata oluştu.

Veri sınıfının içinde başka bir bileşik nesne var. Bunun da [Serializable]özniteliğe sahip olması mı gerekiyor yoksa üst nesneye sahip olması, özyinelemeyi içindeki tüm nesnelere tekrar tekrar uyguluyor mu?

Yanıtlar:


413

Aldığınız iç istisnalara bakın. Hangi alan / mülkün serileştirilmesinde sorun yaşadığını size söyleyecektir.

Alanları / özellikleri, [XmlIgnore]öznitelikle süsleyerek xml serileştirmesinin dışında tutabilirsiniz .

XmlSerializer[Serializable]özniteliği kullanmaz , bu yüzden sorun olduğundan şüpheliyim.


11
Nesnemin bu istisnayı oluşturan bir Uri alanı vardı; Uri sınıfında parametresiz bir yapıcı yoktur. Bahşiş için teşekkürler.
ford

10
Bir google arama ile karşı karşıya geldi - benim özel sorun IListolması gerektiği gibi benim "serileştirilecek" sınıfında bir özellik yaşıyordu List.
Paul Aldred-Bann

7
Kişi "iç istisna" ya nasıl bakar?
David

7
veya bir saate '@exception' ekleyin
arolson101

19
Teşekkürler, bu cevap bana yardımcı oldu. Başlangıçta iç istisnalara baktım ve sadece ana sınıftan bahsetti. Ancak, innrexceptions'ın içgüdüsel düşüncelerini inceleyebileceğimi fark ettim ve nihayetinde, 5 seviye aşağı, sorunu buldum. Çelişkili sınıflarım vardı. Teşekkürler.
Louis van Tonder

111

Serileştirilmiş sınıfların varsayılan (yani parametresiz) yapıcılara sahip olması gerektiğini unutmayın. Hiçbir kurucunuz yoksa, sorun değil; ancak parametreli bir kurucunuz varsa, varsayılanı da eklemeniz gerekir.


4
Hatırlatma için teşekkürler! Bu küçük bir açıklama ile bir çalışma zamanı hatası nefret ediyorum.
Jared Updike

Bu hatayı tekrar tekrar yapmaya devam ediyorum. parametresiz bir kurucu kullanmamı hatırlattığın için teşekkürler ^^
aZtraL-EnForceR

25

Ben benzer bir sorun vardı ve bu serileştirici aynı adı vardı (biri diğerinin bir alt sınıf oldu) 2 sınıf arasında ayırt edemediği ortaya çıktı. İç istisna şöyle görünüyordu:

'BaseNamespace.Class1 Türleri' ve 'BaseNamespace.SubNamespace.Class1' türlerinin her ikisi de ad alanından 'Class1' XML tür adını kullanır ''. Tür için benzersiz bir XML adı ve / veya ad alanı belirtmek üzere XML niteliklerini kullanın.

Burada BaseNamespace.SubNamespace.Class1, BaseNamespace.Class1 öğesinin bir alt sınıfıdır.

Ne yapmak için gerekli sınıflardan birine bir öznitelik eklemek oldu (temel sınıfa ekledi):

[XmlType("BaseNamespace.Class1")]

Not: Daha fazla sınıf katmanınız varsa, bunlara da bir nitelik eklemeniz gerekir.


Bu benim için problemi çözdü, teşekkürler +1; Her biri bir Config iç sınıfına sahip birkaç Processor * nesnesiyle benzer bir ayarım vardı. Çalışma zamanı SomeNS.Processor1.Config ve SomeNS.Processor2.Config arasında ayrım yapamadı.
damix911


6

En yaygın nedenlerim:

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


5

Belirli nitelikleri (örneğin Sözlük veya herhangi bir sınıf) işlemeniz gerekiyorsa , daha ayrıntılı kodlama pahasına daha fazla özgürlük sağlayacak olan IXmlSerialiable arabirimini uygulayabilirsiniz .

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'ı "genişletmek" için sofistike bir yol uygulamak için zarif bir yol gösteren ilginç bir makale var .


Makale şöyle diyor:

IXmlSerializable resmi belgelerde yer almaktadır, ancak belgelerde genel kullanıma yönelik olmadığını ve bunun ötesinde hiçbir bilgi verilmemektedir. Bu, geliştirme ekibinin bu genişletilebilirlik kancasını yolda değiştirme, devre dışı bırakma ve hatta tamamen kaldırma hakkını saklamak istediğini gösterir. Bununla birlikte, bu belirsizliği kabul etmeye ve gelecekte olası değişikliklerle uğraşmaya istekli olduğunuz sürece, bundan yararlanamayacağınız hiçbir sebep yoktur.

Çünkü bu, IXmlSerializableçok karmaşık uygulamalardan kaçınmak için kendi sınıflarınızı uygulamanızı öneririm .

... özel XmlSerializersınıfımızı yansıma kullanarak uygulamak kolay olabilir .


4

.Net 2.0'daki Dictionary sınıfının XML kullanarak serileştirilemediğini, ancak ikili serileştirme kullanıldığında iyi serileştiğini keşfettim.

Burada bir iş buldum .


3

Son zamanlarda yeni bir özellik eklerken bu bir web başvurusu kısmi sınıf var. Otomatik oluşturulan sınıf aşağıdaki öznitelikleri ekliyordu.

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

Otomatik oluşturulan dizide sondan daha yüksek bir sipariş ile benzer bir özellik eklemek gerekiyordu ve bu benim için sabit.


3

Ben sadece aynı hatayı aldım ve tür bir özellik IEnumerable<SomeClass>sorun olduğunu keşfettim . IEnumerableDoğrudan serileştirilemediği anlaşılıyor .

Bunun yerine, kişi kullanabilir List<SomeClass>.


2

Ben de Serializable özniteliği nesne üzerinde olması gerektiğini düşündüm ama tam bir noob (ben bir gece kodlama oturumunun ortasında değilim) sürece SnippetCompiler aşağıdaki çalışmaları :

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 genel özellikleri üzerinde yansıma kullanıyor hayal ediyorum.


1

Siparişin arka arkaya iki öğe için aynı olduğu bir durumum vardı

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

.... bazı kodlar ...

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

Sınıftaki her yeni Özellik için siparişi birer birer artırmak için kodu değiştirdiğimde, hata gitti.


1

Ben bir datatype - sahip bir özellik oluştururken aynı hatayı alıyordum Type. Bu konuda bir hata alıyordum - türü yansıtan bir hata oluştu. Hata ayıklama dock her istisna 'InnerException' kontrol etti ve Typebenim durumumda (ki ) belirli alan adını aldım . Çözüm aşağıdaki gibidir:

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

0

Ayrıca, kullanıcı arabirimi denetimlerini serileştiremeyeceğinizi ve panoya iletmek istediğiniz herhangi bir nesnenin serileştirilebilir olması gerektiğini, aksi takdirde diğer işlemlere aktarılamayacağını unutmayın.



0

Aynı sorunu vardı ve benim durumumda nesne bir ReadOnlyCollection vardı. Koleksiyonun serileştirilebilmesi için Add yöntemi kullanması gerekir.


Bu soruya uygun bir cevap değil. Bu soruya daha başka 15 cevap daha var. Cevabınızın diğerlerinden daha iyi olduğunu düşünüyorsanız, daha fazla ayrıntı vermelisiniz. Bazı kod ve çıkış snippet'lerinin sağlanması her zaman kullanıcılara yardımcı olur. Yanıtlarınızı göndermeden önce aşağıdakileri okumayı düşünün -> stackoverflow.com/help/how-to-answer
Amit Phaltankar

0

Şimdiye kadar burada açıklananlara biraz farklı bir çözümüm var, bu yüzden gelecekteki herhangi bir uygarlık için benim!

Orijinal tür bir TimeSpanve daha sonra bir değiştirildi olarak "zaman" bir veri türü bildirmişti String:

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

ancak gerçek tür bir dizedir

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

DateTypeözelliği kaldırarak Xmlserileştirilebilir

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

Veya

[XmlIgnore]
string [] strFielsName {get;set;}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.