2010-12-01 13 views
5

IXmlSerializable nesnesindeki IXmlSerializable nesnesindeki alanlara XmlAttributesOverrides kullanarak nasıl erişirim?Erişim XmlAttributesOverrides eklenen öznitelikler IXmlSerializable yöntemleriyle

Numune IXmlSerializable nesnesi:

public class Person : SomeBaseClass, IXmlSerializable 
{ 
    public string Name1; 

    public string Name2; 

    [XmlIgnore] 
    public string Name3; 

    public Person() 
    { 
    } 

    public Person(string first, string second, string third) 
    { 
     Name1 = first; 
     Name2 = second; 
     Name3 = third; 
    } 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     // .... 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     FieldInfo[] finfo = this.GetType().GetFields(); 

     foreach (FieldInfo finf in finfo) 
     { 
      FieldAttributes attr = finf.Attributes; 
      object[] atts = finf.GetCustomAttributes(true); 

      if (atts.Length == 0) 
      { 
       // handle field with no attributes ... should be just Name1 
       // but also get Name2 since XmlAttributOverrides' XmlIgnore is not 
       // included with GetCustomAttributes results. 
       writer.WriteElementString(finf.Name, (string)finf.GetValue(this)); 
      } 
      else 
      { 
       // handle field with attributes ... should be Name2 and Name3 
       // but only get Name3 via [XmlIgnore] compiler generated attribute 
      } 
     } 
    } 
} 

Tipik geçersiz kılma oluşturma:

 // parent app ... 

    public XmlSerializer CreateOverrider() 
    { 
     XmlAttributeOverrides xOver = new XmlAttributeOverrides(); 
     XmlAttributes attrs = new XmlAttributes(); 

     attrs.XmlIgnore = true; 
     xOver.Add(typeof(Person), "name2", attrs); 

     XmlSerializer xSer = new XmlSerializer(typeof(Person), xOver); 
     return xSer; 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     // Custom XmlSerialize 
     Person pson = new Person("First", "Second", "Third"); 

     XmlSerializer serializer = CreateOverrider(); 
     TextWriter writer = new StreamWriter("PersonOverride.xml"); 

     serializer.Serialize(writer, pson); 
     writer.Close(); 
    } 

    // etc ... 

düzenlendi Çıktı:

<?xml version="1.0" encoding="utf-8"?><Person><Name1>First</Name1><Name2>Second</Name2></Person> 

Ben SomeBaseClass 'dan miras sorunları aşmak için IXmlSerializable kullanmak gerekir.

Sorun, GetCustomArributes'un XmlAttributeOverrides koleksiyonuna eklenen özelliklerden herhangi birini iade etmemesidir - ya da yanlış yapıyorum!

Ayrıca, GetCustomAttributes, bu ek öznitelikleri döndürmek için SORUMLU DEĞİLDİR veyaIXmlSerializable sınıfında kullanmamam gerekir.

Yani ... herhangi bir fikir veya alternatif. Zaman ayırdığınız için teşekkürler.

+0

herhangi özel bir nedeni sadece doğrudan Kişi bunları sınıfa enjekte edemez neden var mı? Örneğin, set sınıfında SetOverrides (XmlAttributeOverrides overrides) yöntemini yapın ve serileştirilmeden hemen önce arayın. –

+0

@OndrejSvejdar Bu seri hale getirme için çalışır, ancak seri hale getirme için DEĞİLDİR. –

cevap

0

Bunu yapmanın bir yolu yok. IXmlSerializableIXmlSerializable olmayan nesneler verildiğinde, XmlSerializer diziselleştirici sınıfları üreteceği için nedeni, nedeni. Bu XML Geçersiz Kılma Öznitelikleri, bu sınıfları farklı şekilde derlemek için kullanılacaktır. XML, Özelliklerini Geçersiz Kılar Geçersizleştirme veya serileştirme sırasında çalışma zamanında uygulanmaz; Bu yüzden erişilebilir değiller.

IXmlSerializable numaralı sınıfları, bir seri hale getirici sınıfı oluşturmaz. XML Override Attributes kullanmak istiyorsanız, serializer sınıfı derleyicisini geçersiz kılmanız gerekmeyecektir. yerine Person bu uygulaması kullanmayın ve size verilen geçersiz kılma dayalı için serileştirici sınıf oluşturmak izin (aynı zamanda daha hızlı birçok birçok kez çalışacak):

public class Person : SomeBaseClass 
{ 
    public string Name1; 

    public string Name2; 

    [XmlIgnore] 
    public string Name3; 

    public Person() 
    { 
    } 

    public Person(string first, string second, string third) 
    { 
     Name1 = first; 
     Name2 = second; 
     Name3 = third; 
    } 
} 

Elbette Ayrıca kendi seri hale sınıf derleyici yazmak için bekliyoruz ama bu, burada neyin sığabileceğinden biraz daha fazla söz konusu. Ama uygulama aşağıdaki gibi görünmelidir:

public static Type GeneratePersonSerializer(XmlAttributeOverrides overrides) { 
    //here compile a class to generate a Type inheriting from IXmlSerializable 
    //the serializer logic in this class should be generated by taking into 
    //account the given XmlAttributeOverrides 
    //the type returned should be the Type passed into new XmlSerializer(Type type) 
} 
0

Eğer seri hale getirmek alanlara başvurular depolar nerede Fieldınfo listesiyle XmlWriter kendi uygulama oluşturmak için sunabilir. Ardından, hedef türün örneğine (örnek olarak Person) aktarın ve yalnızca bunları serileştirin. Ana yöntemde, 2 serileştirme örneğini görebilirsiniz: Name1 ve Name1 olmadan. Ayrıca yansıma performansının yavaş olduğunu fark etmelisiniz, bu nedenle sadece bool alanı (bool DoNotSerializeName1) oluşturabilir ve doğruysa Name1 serileştirmesini dikkate almayın. Umarım birileri için yararlı olur.

Kişi tipi ve seri hale örneği:

using System; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Text; 
using System.Xml; 
using System.Xml.Schema; 
using System.Xml.Serialization; 

namespace XmlCustomSerializer 
{ 
    public class Person : IXmlSerializable 
    { 
     public string Name1; 

     public string Name2; 

     [XmlIgnore] 
     public string Name3; 

     public Person() 
     { 
     } 

     public Person(string first, string second, string third) 
     { 
      Name1 = first; 
      Name2 = second; 
      Name3 = third; 
     } 

     public XmlSchema GetSchema() 
     { 
      return null; 
     } 

     public void ReadXml(XmlReader reader) 
     { 
      // .... 
     } 

     private static FieldInfo[] _cachedFields = null; 
     public void WriteXml(XmlWriter writer) 
     { 
      var customWriter = writer as XmlCustomWriter; 
      if (customWriter == null) 
       throw new ArgumentException("writer"); 

      if (_cachedFields == null) 
      { 
       _cachedFields = typeof(Person).GetFields(); 
      } 

      foreach (FieldInfo finf in customWriter.FieldsToSerialize) 
      { 
       if (_cachedFields.Contains(finf)) 
       { 
        writer.WriteElementString(finf.Name, (string)finf.GetValue(this)); 
       } 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var person = new Person 
      { 
       Name1 = "Some", 
       Name2 = "Person", 
       Name3 = "Name" 
      }; 

      var settings = new XmlWriterSettings { Indent = true, Encoding = Encoding.ASCII }; 
      var allFields = typeof(Person).GetFields(); 

      XmlSerializer xSer = new XmlSerializer(typeof(Person)); 

      using (var stream = new MemoryStream()) 
      { 
       var xmlCustomWriter = new XmlCustomWriter(
        XmlWriter.Create(new StreamWriter(stream), settings)); 

       //serialize all fields 
       xmlCustomWriter.FieldsToSerialize = allFields; 

       xSer.Serialize(xmlCustomWriter, person); 

       stream.Seek(0, SeekOrigin.Begin); 
       Console.WriteLine(new StreamReader(stream).ReadToEnd()); 
      } 

      using (var stream = new MemoryStream()) 
      { 
       var xmlCustomWriter = new XmlCustomWriter(
        XmlWriter.Create(new StreamWriter(stream), settings)); 

       //serialize 2 fields 
       xmlCustomWriter.FieldsToSerialize = allFields.Skip(1); 

       xSer.Serialize(xmlCustomWriter, person); 

       stream.Seek(0, SeekOrigin.Begin); 
       Console.WriteLine(new StreamReader(stream).ReadToEnd()); 
      } 

      Console.Read(); 
     } 
    } 
} 

XmlCustomWriter uygulaması:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Xml; 

namespace XmlCustomSerializer 
{ 
    public class XmlCustomWriter : XmlWriter 
    { 
     private readonly XmlWriter _innerWriter; 

     public XmlCustomWriter(XmlWriter innerWriter) 
     { 
      if (innerWriter == null) 
       throw new ArgumentNullException("innerWriter"); 
      _innerWriter = innerWriter; 
      FieldsToSerialize = Enumerable.Empty<FieldInfo>(); 
     } 

     public IEnumerable<FieldInfo> FieldsToSerialize { get; set; } 

     #region Implement XmlWriter 
     public override void Flush() 
     { 
      _innerWriter.Flush(); 
     } 

     public override string LookupPrefix(string ns) 
     { 
      return _innerWriter.LookupPrefix(ns); 
     } 

     public override void WriteBase64(byte[] buffer, int index, int count) 
     { 
      _innerWriter.WriteBase64(buffer, index, count); 
     } 

     public override void WriteCData(string text) 
     { 
      _innerWriter.WriteCData(text); 
     } 

     public override void WriteCharEntity(char ch) 
     { 
      _innerWriter.WriteCharEntity(ch); 
     } 

     public override void WriteChars(char[] buffer, int index, int count) 
     { 
      _innerWriter.WriteChars(buffer, index, count); 
     } 

     public override void WriteComment(string text) 
     { 
      _innerWriter.WriteComment(text); 
     } 

     public override void WriteDocType(string name, string pubid, string sysid, string subset) 
     { 
      _innerWriter.WriteDocType(name, pubid, sysid, subset); 
     } 

     public override void WriteEndAttribute() 
     { 
      _innerWriter.WriteEndAttribute(); 
     } 

     public override void WriteEndDocument() 
     { 
      _innerWriter.WriteEndDocument(); 
     } 

     public override void WriteEndElement() 
     { 
      _innerWriter.WriteEndElement(); 
     } 

     public override void WriteEntityRef(string name) 
     { 
      _innerWriter.WriteEntityRef(name); 
     } 

     public override void WriteFullEndElement() 
     { 
      _innerWriter.WriteFullEndElement(); 
     } 

     public override void WriteProcessingInstruction(string name, string text) 
     { 
      _innerWriter.WriteProcessingInstruction(name, text); 
     } 

     public override void WriteRaw(string data) 
     { 
      _innerWriter.WriteRaw(data); 
     } 

     public override void WriteRaw(char[] buffer, int index, int count) 
     { 
      _innerWriter.WriteRaw(buffer, index, count); 
     } 

     public override void WriteStartAttribute(string prefix, string localName, string ns) 
     { 
      _innerWriter.WriteStartAttribute(prefix, localName, ns); 
     } 

     public override void WriteStartDocument(bool standalone) 
     { 
      _innerWriter.WriteStartDocument(standalone); 
     } 

     public override void WriteStartDocument() 
     { 
      _innerWriter.WriteStartDocument(); 
     } 

     public override void WriteStartElement(string prefix, string localName, string ns) 
     { 
      _innerWriter.WriteStartElement(prefix, localName, ns); 
     } 

     public override WriteState WriteState 
     { 
      get { return _innerWriter.WriteState; } 
     } 

     public override void WriteString(string text) 
     { 
      _innerWriter.WriteString(text); 
     } 

     public override void WriteSurrogateCharEntity(char lowChar, char highChar) 
     { 
      _innerWriter.WriteSurrogateCharEntity(lowChar, highChar); 
     } 

     public override void WriteWhitespace(string ws) 
     { 
      _innerWriter.WriteWhitespace(ws); 
     } 
     #endregion Implement XmlWriter 
    } 
} 
İlgili konular