SORU
21 AĞUSTOS 2008, PERŞEMBE


XML Seri hale getirme ve Miras Türleri

previous question İ aşağıdaki nesne modeli XML seri hale getirmek için almaya çalışıyoruz. Ama şimdi bir sorun haline (ne şaşırtıcı!) çalıştırmak.

Benim derdim, beton türetilmiş bir tür tarafından doldurulur soyut bir temel sınıf türü olan bir koleksiyon var.

XML sınıfları dahil tüm öznitelikleri eklemek iyi olur diye düşündüm ve her şey çok güzel olurdu. Ne yazık ki, durum böyle değil!

Google üzerinde biraz araştırma yaptım ve şimdi anlıyorumnedenişe yaramıyor. BuXmlSerializer aslında yapmak daha akıllıca bir yansıması amacıyla, nesneleri getirmek için/XML, ve o zamandan bu yana dayalı, soyut tip, anlamaya ne konuşuyor. Güzel.

Yaptım rastlamak this page CodeProject, ki öyle de görünüyor olabilir, size bir sürü (henüz okuma/tüketmek tam olarak), ama dedim gibi getir bu sorunun StackOverflow masa da, eğer herhangi bir düzgün kesmek/hileler için bu kadar çalışan en hızlı/en hafif şekilde mümkün.

Ayrıca eklemem gereken bir şeyYOKXmlInclude rota aşağı gitmek istiyorum. Sadece çok fazla denge var, ve sistemin bu alanda gerçek bir bakım baş ağrısı olurdu bu kadar ağır geliştirme aşamasında.

CEVAP
12 HAZİRAN 2009, Cuma


Sorun Çözüldü!

Nihayet oraya (kuşkusuz bir . bu kadar TAMAM, ^strong>çokhere!) yardım.

Yani özetler:

Hedefleri:

  • Bu aşağı gitmek istemedimXmlıncludeyol bakım baş ağrısı nedeniyle.
  • Bir çözüm bulundu sonra, diğer uygulamalarda uygulamak için hızlı olmak istedim.
  • Soyut türleri koleksiyonları, hem de tek tek soyut özellikleri kullanılabilir.
  • Gerçekten "" beton sınıfları. özel şeyler için rahatsız etmek istemedim

Tespit edilen Sorunlar/Dikkat edilecek Noktalar:

  • XmlSerializeryok çok güzel yansıma, ama öyleçoksoyut türleri söz konusu olduğunda sınırlı (yani sadece soyut bir tip kendisi, alt sınıflar değil, örnekleri ile çalışır).
  • Xml dekoratörler XmlSerializer özelliklerini bulur nasıl davrandığını tanımlamak bağlıyor. Fiziksel şekli de belirtilebilir, ama bu bir oluşturursıkı kavramasınıf ve seri hale getirici (iyi değil) arasında.
  • Uygulayan bir sınıf oluşturarak kendi XmlSerializer sağlayabilirizIxmlserializable.

Çözüm

Hangi ile çalışıyor soyut türü genel tür belirlemek genel bir sınıf oluşturdum. Bu sınıf"," soyut türü ve elimizden beri beton tipi sabit-kod döküm (yani XmlSerializer daha fazla bilgi alabiliriz) arasında. çevirmek için yeteneği verir

Ben o hayataIxmlserializablearayüz, bu XML için beton sınıfı türü yazıyoruz sağlamalıyız seri hale getirilirken yalındır güzel, ama, de seri hale getirilirken, geri dökme. Ayrıca önemli olmalı unutmayıntam olarak nitelenmişiki sınıf derlemeleri farklı muhtemeldir. Tabii ki burada olması gereken küçük bir tür denetleme falan yok.

XmlSerializer olamaz dökme beri, bunu yapmak için kod sağlamak için ihtiyacımız var, örtülü daha sonra operatör aşırı yüklenmesi (ben bile bunu yapabileceğini biliyordum!).

Bu AbstractXmlSerializer kodu bu:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Utility.Xml
{
    public class AbstractXmlSerializer<AbstractType> : IXmlSerializable
    {
        // Override the Implicit Conversions Since the XmlSerializer
        // Casts to/from the required types implicitly.
        public static implicit operator AbstractType(AbstractXmlSerializer<AbstractType> o)
        {
            return o.Data;
        }

        public static implicit operator AbstractXmlSerializer<AbstractType>(AbstractType o)
        {
            return o == null ? null : new AbstractXmlSerializer<AbstractType>(o);
        }

        private AbstractType _data;
        /// <summary>
        /// [Concrete] Data to be stored/is stored as XML.
        /// </summary>
        public AbstractType Data
        {
            get { return _data; }
            set { _data = value; }
        }

        /// <summary>
        /// **DO NOT USE** This is only added to enable XML Serialization.
        /// </summary>
        /// <remarks>DO NOT USE THIS CONSTRUCTOR</remarks>
        public AbstractXmlSerializer()
        {
            // Default Ctor (Required for Xml Serialization - DO NOT USE)
        }

        /// <summary>
        /// Initialises the Serializer to work with the given data.
        /// </summary>
        /// <param name="data">Concrete Object of the AbstractType Specified.</param>
        public AbstractXmlSerializer(AbstractType data)
        {
            _data = data;
        }

        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null; // this is fine as schema is unknown.
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            // Cast the Data back from the Abstract Type.
            string typeAttrib = reader.GetAttribute("type");

            // Ensure the Type was Specified
            if (typeAttrib == null)
                throw new ArgumentNullException("Unable to Read Xml Data for Abstract Type '"   typeof(AbstractType).Name  
                    "' because no 'type' attribute was specified in the XML.");

            Type type = Type.GetType(typeAttrib);

            // Check the Type is Found.
            if (type == null)
                throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '"   typeof(AbstractType).Name  
                    "' because the type specified in the XML was not found.");

            // Check the Type is a Subclass of the AbstractType.
            if (!type.IsSubclassOf(typeof(AbstractType)))
                throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '"   typeof(AbstractType).Name  
                    "' because the Type specified in the XML differs ('"   type.Name   "').");

            // Read the Data, Deserializing based on the (now known) concrete type.
            reader.ReadStartElement();
            this.Data = (AbstractType)new
                XmlSerializer(type).Deserialize(reader);
            reader.ReadEndElement();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            // Write the Type Name to the XML Element as an Attrib and Serialize
            Type type = _data.GetType();

            // BugFix: Assembly must be FQN since Types can/are external to current.
            writer.WriteAttributeString("type", type.AssemblyQualifiedName);
            new XmlSerializer(type).Serialize(writer, _data);
        }

        #endregion
    }
}

Oradan, nasıl XmlSerializer seri hale getirici ile çalışmak bizim için söyle varsayılan yerine muyuz? Örneğin Xml öznitelikleri type özelliği içinde bizim yazın geçmek zorundayız:

[XmlRoot("ClassWithAbstractCollection")]
public class ClassWithAbstractCollection
{
    private List<AbstractType> _list;
    [XmlArray("ListItems")]
    [XmlArrayItem("ListItem", Type = typeof(AbstractXmlSerializer<AbstractType>))]
    public List<AbstractType> List
    {
        get { return _list; }
        set { _list = value; }
    }

    private AbstractType _prop;
    [XmlElement("MyProperty", Type=typeof(AbstractXmlSerializer<AbstractType>))]
    public AbstractType MyProperty
    {
        get { return _prop; }
        set { _prop = value; }
    }

    public ClassWithAbstractCollection()
    {
        _list = new List<AbstractType>();
    }
}

Burada gördüğünüz gibi, bir toplama ve tek bir özellik maruz olduğumuz ve yapmamız gereken tüm ekleyinyazınXml bildirimi için parametre adında, kolay! :D

NOT: Eğer bu kodu kullanırsanız, gerçekten bir-haykır memnun olurum. Ayrıca toplum için daha fazla kişi sürücü:) yardımcı olacaktır

Şimdi, ama ne için hepsi pro ve con beri cevapları burada yapmak emin olarak. Yararlı olduğunu hissediyorum (o değildi o hiçbir suç) upmod ve ben bir kez bu kadar yakın kapalı rep :) ederim

Çözmek için sorun ve iyi eğlenceli ilginç! :)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Alexander Johnson

    Alexander Jo

    26 Temmuz 2008
  • Autocar

    Autocar

    11 Mart 2006
  • Kurtindo Pop Games

    Kurtindo Pop

    2 HAZİRAN 2013