5

xmlファイルからいくつかの設定を逆シリアル化しようとしています。問題のあるプロパティ/基になるフィールドは、と呼ばれるものAlertColorsです。基になるフィールドを白、黄、赤に初期化して、このクラスの新しいインスタンスに有効な色設定があることを確認します。しかし、逆シリアル_colorArgb化すると、6つの値になり、最初の3つは初期化値で、最後の3つはxmlファイルから読み取られる値です。ただし、プロパティAlertColorsはフィールドに追加されませんが、その要素が変更されます。なぜ6色のフィールドになってしまうのですか?

コードは次のとおりです。

    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;
    }

そして、私が逆シリアル化しているxmlファイルの関連部分:

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

3 に答える 3

4

基本的に、それが機能する方法XmlSerializerです。リストが でない限り、null値を設定しようとはしません。特に、ほとんどの場合、サブアイテム リストにはセッターがありません。次のようなものです。

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

(ほとんどの人は、外部の呼び出し元にリストを再割り当てしてほしくないため、内容を変更してもらいたいだけです)。

このため、XmlSerializerは基本的に次のように動作します (単純化しすぎています)。

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

解決策の 1 つは、リストではなく配列を使用することです。常に配列をオブジェクトに割り当てることを想定しているため、配列の場合は次のように実装されます (単純化しすぎています)。

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

ただし、固定数の値の場合、より単純な実装は次のようになります。

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

(私の言いたいことがわかるなら)

于 2012-10-24T09:49:28.807 に答える
2

データ型を変更せずに目的の結果を得るには、通常の XmlSerializer の代わりに DataContractSerializer (System.Runtime.Serialization を使用) を使用できます。デフォルトのコンストラクターを呼び出さないため、6 色ではなく 3 色になります。

var ser = new DataContractSerializer(typeof(Settings));
var reader = new FileStream(@"c:\SettingsFile.xml", FileMode.Open);
var deserializedSettings = (Settings)ser.ReadObject(reader);
于 2015-03-28T00:49:16.207 に答える