XML序列化追加到列表 [英] Xml deserialization appends to list

查看:145
本文介绍了XML序列化追加到列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从XML文件反序列化的一些设置。有问题的物业/基础字段是一个叫 AlertColors 。我初始化基础字段到白,黄,红三色,以确保这个类的一个新实例具有有效的颜色设置。但是,当我反序列化, _colorArgb 与六个值结束了,前三种是初始值和最后3个是从XML文件中读取的。但物业 AlertColors 不追加到现场,但改变其元素。 ?为什么我结束了六色场



下面的代码:

 私人列表< INT> _colorArgb =新的List< INT>(新INT [] {Color.White.ToArgb(),Color.Yellow.ToArgb(),Color.Red.ToArgb()}); 

公开名单< INT> AlertColors
{
得到
{
返回_colorArgb;
}


{
的for(int i = 0; I< Math.Min(_colorArgb.Count,value.Count);我++)
{
如果(_colorArgb [I] =值[I]!)
{
HasChanged = TRUE;
}
}

_colorArgb =价值;
}
}

公共BOOL反序列化(字符串文件路径)
{
如果(!File.Exists(文件路径))
$ { b $ b Logger.Log(错误而载入的设置文件不存在。);

返回false;
}

的FileStream FILESTREAM = NULL;


{
FILESTREAM =新的FileStream(文件路径,FileMode.Open);
System.Xml.Serialization.XmlSerializerFactory xmlSerializerFactory =
新XmlSerializerFactory();
System.Xml.Serialization.XmlSerializer的XmlSerializer =
xmlSerializerFactory.CreateSerializer(typeof运算(设置));

设置deserializedSettings =(设置)xmlSerializer.Deserialize(FILESTREAM);

的getSettings(deserializedSettings);

Logger.Log(+文件路径设置已经从文件加载成功);
}
赶上(IOException异常IOException异常)
{
Logger.Log(+ iOException.Message错误加载设置。);

返回false;
}
赶上(ArgumentException的ArgumentException的)
{
Logger.Log(+ argumentException.Message错误加载设置。);

返回false;
}
赶上(InvalidOperationException异常InvalidOperationException异常)
{
Logger.Log(错误加载设置。不支持设置文件。+
invalidOperationException.Message) ;

返回false;
}
终于
{
如果(FILESTREAM!= NULL)
fileStream.Close();

=文件路径文件路径;
}

返回真;
}

保护无效的getSettings(设置设置)
{
AlertColors = settings.AlertColors;
}

和我正在反序列化的XML文件中的相关部分:

 < AlertColors> 
< INT -1个< / INT>
< INT> -15℃; / INT>
< INT>&-65536 LT; / INT>
< / AlertColors>


解决方案

基本上,这是多么 XmlSerializer的的作品。除非该列表是,它永远不会希望去尝试,并设置一个值。尤其是,的时间,分项列出的没有的setter - 他们是这样的话:

 私人只读表<儿童>孩子=新的List<儿童>(); 
公开名单<儿童>儿童{{返回儿童; }}



(因为大多数人不希望外部呼叫者为重新分配名单;他们只是希望他们改变的内容)



由于这个原因,的XmlSerializer 基本操作类似于(过度简化):

 无功名单= yourObj.SomeList; 
的foreach({数据中找到适合孩子})
list.Add({新项目});



一个解决方法是使用一个数组,而不是一个列表;它总是期望将数组分配回对象,所以对于一个数组它的实现更象(囫囵吞枣):

 无功名单=新名单,LT; SOMETYPE>(); 
的foreach({数据中找到适合孩子})
list.Add({新项目});
yourObj.SomeList = list.ToArray();



然而,对于一个固定数目的值,一简单的实现可能只是:



 公共富值1 {获取;设置;} 
公共富值2 {获取;集;}
公共美孚值3 {得到;设置;}

(如果你明白我的意思)


I'm trying to deserialize some settings from an xml file. The problematic property/underlying field is one called AlertColors. I initialize the underlying field to white, yellow, and red to make sure that a new instance of this class has a valid color setting. But when I deserialize, _colorArgb ends up with six values, first three are the initialization values and the last three are the ones that are read from the xml file. But the property AlertColors do not append to the field, but changes its elements. Why do I end up with a field with six colors?

Here's the code:

    private List<int> _colorArgb = new List<int>(new int[] { Color.White.ToArgb(), Color.Yellow.ToArgb(), Color.Red.ToArgb() });   

    public List<int> AlertColors
    {
        get
        {
            return _colorArgb;
        }

        set
        {
            for (int i = 0; i < Math.Min(_colorArgb.Count, value.Count); i++)
            {
                if (_colorArgb[i] != value[i])
                {
                    HasChanged = true;
                }
            }

            _colorArgb = value;
        }
    }

    public bool Deserialize(string filePath)
    {
        if (!File.Exists(filePath))
        {
            Logger.Log("Error while loading the settings. File does not exist.");

            return false;
        }

        FileStream fileStream = null;

        try
        {
            fileStream = new FileStream(filePath, FileMode.Open);
            System.Xml.Serialization.XmlSerializerFactory xmlSerializerFactory =
                new XmlSerializerFactory();
            System.Xml.Serialization.XmlSerializer xmlSerializer =
                xmlSerializerFactory.CreateSerializer(typeof(Settings));

            Settings deserializedSettings = (Settings)xmlSerializer.Deserialize(fileStream);

            GetSettings(deserializedSettings);

            Logger.Log("Settings have been loaded successfully from the file " + filePath);
        }
        catch (IOException iOException)
        {
            Logger.Log("Error while loading the settings. " + iOException.Message);

            return false;
        }
        catch (ArgumentException argumentException)
        {
            Logger.Log("Error while loading the settings. " + argumentException.Message);

            return false;
        }
        catch (InvalidOperationException invalidOperationException)
        {
            Logger.Log("Error while loading the settings. Settings file is not supported." +
                invalidOperationException.Message);

            return false;
        }
        finally
        {
            if (fileStream != null)
                fileStream.Close();

            FilePath = filePath;
        }

        return true;
    }

    protected void GetSettings(Settings settings)
    {
        AlertColors = settings.AlertColors;
    }

And the relevant part of the xml file that I'm deserializing:

  <AlertColors>
    <int>-1</int>
    <int>-15</int>
    <int>-65536</int>
  </AlertColors>

解决方案

Basically, that's just how XmlSerializer works. Unless the list is null, it never expects to try and set a value. In particular, most of the time, sub-item lists don't have a setter - they are things like:

private readonly List<Child> children = new List<Child>();
public List<Child> Children { get { return children; } }

(because most people don't want external callers to reassign the list; they just want them to change the contents).

Because of this, XmlSerializer operates basically like (over-simplifying):

var list = yourObj.SomeList;
foreach({suitable child found in the data})
    list.Add({new item});

One fix is to use an array rather than a list; it always expects to assign an array back to the object, so for an array it is implemented more like (over-simplifying):

var list = new List<SomeType>();
foreach({suitable child found in the data})
    list.Add({new item});
yourObj.SomeList = list.ToArray();

However, for a fixed number of values, a simpler implementation might be just:

public Foo Value1 {get;set;}
public Foo Value2 {get;set;}
public Foo Value3 {get;set;}

(if you see what I mean)

这篇关于XML序列化追加到列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆