2

C#、.NET 3.5 の XmlSerializer を介してシリアル化/逆シリアル化されているオブジェクトを取得しました。プロパティの 1 つ (および将来的にはさらに追加) はコレクションです: T は列挙値です。これにより、正常にシリアル化/逆シリアル化されます。

また、シリアル化されたバージョンに値が設定されていない場合に備えて、「デフォルト値」メカニズムを使用してオブジェクトのデフォルト値を提供しています。簡単な例として、これがドンです。

public enum MyEnum {
  Value1,
  Value2
}

public class Foo
{

  public List SomeSetting{ get; set; }

  public Foo()
  {
    SomeSetting = new List();
    SomeSetting.Add(MyEnum.Value1);
    SomeSetting.Add(MyEnum.Value2);
  }
}

このコードは、オブジェクトの構築時に SomeSetting の既定値を設定するのに適切に機能します。

ただし、SomeSetting の値を持つ xml ファイルを逆シリアル化する場合、この既定値の設定が問題を引き起こします。xml デシリアライザーは SomeSetting コレクションを「リセット」しません。これは、クリーンアップして新しいデータを入力しません。むしろ、既存のデータに追加されます。したがって、xml ファイルにシリアル化された Value1 が含まれている場合、そのファイルを逆シリアル化すると、格納されている値として {Value1, Value2, Value1} を持つ SomeSettings になります。

xml ドキュメントに SomeSetting のデータがない場合にデフォルト値が存在できるようにする方法と、xml ドキュメントにデータがある場合に SomeSetting 値を大規模に置き換える方法が必要です。これどうやってするの?

参考までに、ドキュメント内のプロパティはこれだけではありません。ドキュメントは存在し、他の「単純な」値に対してシリアライズ/デシリアライズされています。ただし、これは問題を引き起こしているプロパティです。今、これをたくさん行う必要があるため、このシナリオをサポートする必要があります。

4

3 に答える 3

1

参考までに - IXMLSerializable インターフェイスでこれを解決しました。このコードは、この 1 つのクラス (YMMV.



        public void WriteXml(XmlWriter writer)
        {
            foreach (PropertyInfo prop in GetType().GetProperties())
            {
                XmlIgnoreAttribute attr;
                if (prop.TryGetAttribute(out attr))
                    continue;

                if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List)))
                {
                    XmlSerializer serializer = new XmlSerializer(prop.PropertyType, new XmlRootAttribute(prop.Name));
                    serializer.Serialize(writer, prop.GetValue(this, null));
                }
                else
                {
                    writer.WriteElementString(prop.Name, prop.GetValue(this, null).ToString());
                }
            }
        }

        public void ReadXml(XmlReader reader)
        {
            if (reader.IsEmptyElement)
                return;

            XmlDocument xDoc = new XmlDocument();
            xDoc.Load(reader);

            Type type = GetType();

            foreach (XmlNode node in xDoc.DocumentElement.ChildNodes)
            {
                PropertyInfo prop = type.GetProperty(node.Name);
                if (prop != null && prop.CanWrite)
                {
                    object value;
                    if (prop.PropertyType.IsEnum)
                    {
                        string stringValue = node.InnerText;
                        value = Enum.Parse(prop.PropertyType, stringValue);
                    }
                    else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List)))
                    {
                        Type enumType = prop.PropertyType.GetGenericArguments()[0];
                        value = Activator.CreateInstance(prop.PropertyType);
                        var addMethod = value.GetType().GetMethod("Add");
                        foreach (XmlNode subNode in node.ChildNodes)
                        {
                            object enumValue = Enum.Parse(enumType, subNode.InnerText);
                            addMethod.Invoke(value, new[] { enumValue });
                        }
                    }
                    else
                    {
                        string stringValue = node.InnerText;
                        value = Convert.ChangeType(stringValue, prop.PropertyType);
                    }
                    prop.SetValue(this, value, null);
                }
            }
        }

        public XmlSchema GetSchema()
        {
            return null;
        }
于 2009-12-30T17:14:15.830 に答える
0

迅速で汚いのは、ISupportInitializeを実装することです。すべての.NETシリアライザー(IIRC)はこのインターフェイスを尊重しEndInit、逆シリアル化後に呼び出します。

この時点でコレクションの内容を確認し、その時点でデフォルトを追加する必要があるかどうかを判断できます。また、最初に使用する前にインスタンスが初期化されているかどうかを確認し、初期化されていない場合は例外をスローすることをお勧めします。これにより、クラスの他のユーザーは、使用する前にインスタンスを初期化する必要があることを確実に知ることができます。

于 2009-12-28T15:14:36.953 に答える
0

自分で XML を解析するのではなく、別の方法として、私が使用した方法を使用できます。ただの提案です。

C# Xml Deserialize とデザインの提案

于 2013-02-08T19:32:29.943 に答える