Сериализация XML интерфейсного свойства

Всего несколько мыслей, авеню или два для исследования.

это возможный иметь функцию, выполняемую каждые 10 секунд и иметь ту проверку "встречная" переменная? Если это возможно, Вы можете иметь на наведении мыши для страницы, можете Вы нет? Если так, используйте событие mouseOver для сброса "встречной" переменной. Если Ваша функция вызвана, и счетчик выше диапазона, который Вы предопределяете, то сделайте свое действие.

Снова, просто некоторые мысли... Надежда это помогает.

79
задан Elad 26 August 2009 в 11:13
поделиться

3 ответа

Это просто внутреннее ограничение декларативной сериализации, когда информация о типе не встроена в вывод.

При попытке преобразовать обратно в

public class Flibble { public object Foo { get; set; } }

Как сериализатор узнает, должно ли это быть int, string, double (или что-то еще) ...

Для выполнения этой работы у вас есть несколько вариантов, но если вы действительно не знаете до времени выполнения, самый простой способ сделать это, вероятно, будет использовать XmlAttributeOverrides .

К сожалению, это будет работать только с базовыми классами, но не с интерфейсами. Лучшее, что вы можете сделать, - это игнорировать свойство, которого недостаточно для ваших нужд.

Если вам действительно нужно оставаться с интерфейсами, у вас есть три реальных варианта:

Скрыть его и обработать в другом свойстве

] Уродливый,

  • У вас нет отвратительных «фальшивых» свойств.
  • вы можете напрямую взаимодействовать со структурой xml, добавляя гибкости / управления версиями
  • Минусы
    • вам может потребоваться повторно реализовать колесо для всех других свойств в классе
  • Проблемы дублирования усилий аналогичны первому.

    Измените свое свойство, чтобы использовать тип упаковки

    public sealed class XmlAnything<T> : IXmlSerializable
    {
        public XmlAnything() {}
        public XmlAnything(T t) { this.Value = t;}
        public T Value {get; set;}
    
        public void WriteXml (XmlWriter writer)
        {
            if (Value == null)
            {
                writer.WriteAttributeString("type", "null");
                return;
            }
            Type type = this.Value.GetType();
            XmlSerializer serializer = new XmlSerializer(type);
            writer.WriteAttributeString("type", type.AssemblyQualifiedName);
            serializer.Serialize(writer, this.Value);   
        }
    
        public void ReadXml(XmlReader reader)
        {
            if(!reader.HasAttributes)
                throw new FormatException("expected a type attribute!");
            string type = reader.GetAttribute("type");
            reader.Read(); // consume the value
            if (type == "null")
                return;// leave T at default value
            XmlSerializer serializer = new XmlSerializer(Type.GetType(type));
            this.Value = (T)serializer.Deserialize(reader);
            reader.ReadEndElement();
        }
    
        public XmlSchema GetSchema() { return(null); }
    }
    

    Использование этого потребовало бы чего-то вроде (в проекте P):

    public namespace P
    {
        public interface IFoo {}
        public class RealFoo : IFoo { public int X; }
        public class OtherFoo : IFoo { public double X; }
    
        public class Flibble
        {
            public XmlAnything<IFoo> Foo;
        }
    
    
        public static void Main(string[] args)
        {
            var x = new Flibble();
            x.Foo = new XmlAnything<IFoo>(new RealFoo());
            var s = new XmlSerializer(typeof(Flibble));
            var sw = new StringWriter();
            s.Serialize(sw, x);
            Console.WriteLine(sw);
        }
    }
    

    , что дает вам:

    <?xml version="1.0" encoding="utf-16"?>
    <MainClass 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     <Foo type="P.RealFoo, P, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <RealFoo>
       <X>0</X>
      </RealFoo>
     </Foo>
    </MainClass>
    

    Это, очевидно, более обременительно для пользователей этого класса, хотя и позволяет избежать большого количества шаблонов.

    Золотая середина может быть объединением идеи XmlAnything в свойство «поддержки» первой техники. Таким образом, большая часть ворчливой работы выполняется за вас, но потребители этого класса не пострадают, кроме путаницы с самоанализом.

    112
    ответ дан 24 November 2019 в 10:11
    поделиться

    Замена интерфейса IModelObject с абстрактным или конкретным типом и использовать наследование с XMLInclude возможно, но это кажется уродливым обходным путем.

    Если возможно использовать абстрактную базу, я бы рекомендовал этот путь. Это все равно будет чище, чем использование сериализации вручную. Единственная проблема, которую я вижу с абстрактной базой, заключается в том, что вам все еще понадобится конкретный тип? По крайней мере, так я использовал его раньше, например:

    public abstract class IHaveSomething
    {
        public abstract string Something { get; set; }
    }
    
    public class MySomething : IHaveSomething
    {
        string _sometext;
        public override string Something 
        { get { return _sometext; } set { _sometext = value; } }
    }
    
    [XmlRoot("abc")]
    public class seriaized
    {
        [XmlElement("item", typeof(MySomething))]
        public IHaveSomething data;
    }
    
    3
    ответ дан 24 November 2019 в 10:11
    поделиться

    К сожалению, нет простого ответа, поскольку сериализатор не знает, что сериализовать для интерфейса. Я нашел более полное объяснение того, как это обойти, на MSDN

    2
    ответ дан 24 November 2019 в 10:11
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: