C# 如何序列化.Net中几个可选元素中的一个?

C# 如何序列化.Net中几个可选元素中的一个?,c#,.net,serialization,C#,.net,Serialization,我有一个有两个参数的类。一个是以分钟为单位的更新时间,另一个是以秒为单位的相同值,如下所示: using System.Xml.Serialization; [XmlRoot(ElementName="config")] public class Config { [XmlElement(ElementName = "update_mins")] public int Minutes { get { return

我有一个有两个参数的类。一个是以分钟为单位的更新时间,另一个是以秒为单位的相同值,如下所示:

using System.Xml.Serialization;

[XmlRoot(ElementName="config")]
public class Config
{
    [XmlElement(ElementName = "update_mins")]
    public int Minutes 
    {
        get
        {
            return this.Seconds / 60;
        }
        set
        {
            this.Seconds = value * 60;
        }
    }

    [XmlElement(ElementName = "update_secs")]
    public int Seconds { get; set; }
}
    [XmlAnyElement]
    public XmlElement[] AllElements
    {
        get
        {
            XmlElement[] value = new XmlElement[0];
            return value;
        }

        set
        {
            if (value != null)
            {
                foreach (XmlElement e in value)
                {
                    switch (e.Name)
                    {
                        case "update_mins":
                            this.Minutes = Convert.ToInt32(e.InnerText);
                            break;
                    }
                }
            }
        }
    }
我得到的xml字符串可以有update_mins或update_secs,但不能两者都有。我需要能够使用这个类来反序列化这些字符串,这样就可以了。我还需要能够对这些类进行searalize并发送它们,但是当我进行serailization时,它包括update_secs和update_mins。像这样:

<config>
  <update_mins>23</update_mins>
  <update_secs>1380</update_secs>
</config>

23
1380
当我想得到这个:

<config>
  <update_secs>1380</update_secs>
</config>

1380
我尝试将XmlIgnore放在update_mins值上,但这阻止了它对元素进行反序列化。有可能做到这一点吗?如果有,如何做到

我的完整代码示例是:

namespace Scrap
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "<config><update_mins>23</update_mins></config>";

            XmlSerializer searializer = new XmlSerializer(typeof(Config));
            Config result = (Config)searializer.Deserialize(new StringReader(s));

            Console.WriteLine("Minutes: " + result.Minutes);
            Console.WriteLine("Seconds: " + result.Seconds);

            Debug.Assert(result.Minutes == 23);
            Debug.Assert(result.Seconds == 1380);

            StringWriter s2w = new StringWriter();
            searializer.Serialize(s2w, result);

            Console.WriteLine(s2w.ToString());

            string xmlResult = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n" +
                "<config xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n" +                
                "  <update_secs>1380</update_secs>\r\n" +
                "</config>";

            Debug.Assert(s2w.ToString() == xmlResult);

            Console.ReadKey(true);
        }
    }

    [XmlRoot(ElementName = "config")]
    public class Config
    {
        [XmlElement(ElementName = "update_mins")]        
        public int Minutes
        {            
            get
            {
                return this.Seconds / 60;
            }    
            set
            {
                this.Seconds = value * 60;
            }
        }

        [XmlElement(ElementName = "update_secs")]
        public int Seconds { get; set; }
    }
}
名称空间碎片
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串s=“23”;
XmlSerializer searializer=新的XmlSerializer(typeof(Config));
Config result=(Config)searializer.Deserialize(新的StringReader);
控制台.WriteLine(“分钟:+结果.Minutes”);
控制台.WriteLine(“秒:+结果.Seconds”);
Assert(result.Minutes==23);
Assert(result.Seconds==1380);
StringWriter s2w=新StringWriter();
序列化(s2w,结果);
Console.WriteLine(s2w.ToString());
字符串xmlResult=“\r\n”+
“\r\n”+
“1380\r\n”+
"";
Assert(s2w.ToString()==xmlResult);
Console.ReadKey(true);
}
}
[XmlRoot(ElementName=“config”)]
公共类配置
{
[XmlElement(ElementName=“update_mins”)]
公共整数分钟
{            
收到
{
返回这个。秒/60;
}    
设置
{
这个。秒=值*60;
}
}
[XmlElement(ElementName=“update_secs”)]
公共整数秒{get;set;}
}
}

我只想在
分钟上使用
[XmlIgnore]
,因为它是

  • 取决于秒数
  • 计算场
  • 数据传输中的冗余

编辑 您提到您无法控制填充哪个元素,它可以是其中一个,也可以是两个

一种可能的解决方案是添加一层抽象

  • 定义内部公共属性,例如
    SecondsXml
    MinutesXml
    ,并让它们读取XML值(定义属性)
  • 保持
    分钟
  • 已加载布尔字段
    \u
  • 每当访问
    Minutes
    Seconds
    时,检查
    \u isLoaded
    ,如果为false,则检查
    SecondsXml
    MinutesXml
    中的值,以确定加载了哪一个,因此相应地设置
    Minutes
    Seconds
如果您不想将
SecondsXml
MinutesXml
定义为公共,请将它们定义为私有,但用于反序列化。

尝试

class Config : IDeserializationCallback
{
    void IDeserializationCallback.OnDeserialization(object sender) 
    {
    }
}


这仍然不是一个理想的解决方案,但我解决这一问题的方法是将[XmlIgnore]添加到Minutes属性(正如Aliostad和其他人所建议的那样),然后添加一个Allegements属性,如下所示:

using System.Xml.Serialization;

[XmlRoot(ElementName="config")]
public class Config
{
    [XmlElement(ElementName = "update_mins")]
    public int Minutes 
    {
        get
        {
            return this.Seconds / 60;
        }
        set
        {
            this.Seconds = value * 60;
        }
    }

    [XmlElement(ElementName = "update_secs")]
    public int Seconds { get; set; }
}
    [XmlAnyElement]
    public XmlElement[] AllElements
    {
        get
        {
            XmlElement[] value = new XmlElement[0];
            return value;
        }

        set
        {
            if (value != null)
            {
                foreach (XmlElement e in value)
                {
                    switch (e.Name)
                    {
                        case "update_mins":
                            this.Minutes = Convert.ToInt32(e.InnerText);
                            break;
                    }
                }
            }
        }
    }

请确保将属性放在属性上,而不是类上。我尝试过这样做,如果传入的消息只有minutes元素,它将停止反序列化。正如我所说,
minutes
不应反序列化。这是一个经过计算的属性。听起来你好像不明白我的问题是什么。我无法控制输入XML消息的时间是分还是秒,因此我必须处理这两种情况。你的答案不符合我的要求。以声明方式实现这一点的唯一方法是创建另一个具有反序列化所用相同属性的类。因此,您可以在原始文件上应用[XmlIgnore]。在常规代码中获取被截断的分钟值的代码味道应该会让您暂停一下。我知道分钟值将被截断,但是为了与旧系统兼容,我需要这样做,并且损失59秒不会是什么大问题。