В общем вот я тут накидал все-таки вариант без заморочек.
Допустим сначала был такой класс конфига:
[XmlRoot("config", IsNullable = false)]
public class Config
{
private static readonly object _lockFlag = new object();
private static Config _instance;
private const string _configFilePath = "settings.xml";
[XmlAttribute("ImportandData")]
public string ImportandData { get; set; }
[XmlArrayAttribute("DatesInfo")]
public DateTime[] DatesInfo { get; set; }
[XmlIgnore]
public static Config Instance
{
get
{
lock (_lockFlag)
{
if (_instance == null)
{
_instance = Load();
}
}
return _instance;
}
}
private Config() { }
public void Save()
{
var xmlSerializer = new XmlSerializer(typeof(Config));
using (var writer = new StreamWriter(_configFilePath, false, System.Text.Encoding.GetEncoding("Windows-1251")))
{
xmlSerializer.Serialize(writer, this);
}
}
private static Config Load()
{
if(!File.Exists(_configFilePath)) return new Config();
var xmlSerializer = new XmlSerializer(typeof (Config));
using (var xmlTextReader = new XmlTextReader(_configFilePath))
{
Config config = (Config) xmlSerializer.Deserialize(xmlTextReader);
return config;
}
}
}
Теперь вместо свойства public DateTime[] DatesInfo мы хотим сделать свойство public Date[] Dates. Для этого переделываем конфиг таким образом:
[XmlRoot("config", IsNullable = false)]
public class Config
{
private static readonly object _lockFlag = new object();
private static Config _instance;
private const string _configFilePath = "settings.xml";
[XmlAttribute("ImportandData")]
public string ImportandData { get; set; }
///<summary>This property is obsolete and is only used internally to support old config versions.</summary>
[XmlArrayAttribute("DatesInfo")]
[EditorBrowsable(EditorBrowsableState.Never)]
public DateTime[] DatesInfo
{
get
{
throw new InvalidOperationException(
"This property is obsolete and is only used internally to support old config versions." );
}
set
{
var dates = from dt in value select new Date { Year = dt.Year, Month = dt.Month, Day = dt.Day };
Dates = dates.ToArray();
}
}
[XmlArrayAttribute("Dates")]
public Date[] Dates { get; set; }
[XmlIgnore]
public static Config Instance
{
get
{
lock (_lockFlag)
{
if (_instance == null)
{
_instance = Load();
}
}
return _instance;
}
}
private Config() { }
public void Save()
{
var attrs = new XmlAttributes { XmlIgnore = true };
var attrOverrides = new XmlAttributeOverrides();
attrOverrides.Add(typeof(Config), "DatesInfo", attrs);
var xmlSerializer = new XmlSerializer(typeof(Config), attrOverrides);
using (var writer = new StreamWriter(_configFilePath, false, System.Text.Encoding.GetEncoding("Windows-1251")))
{
xmlSerializer.Serialize(writer, this);
}
}
private static Config Load()
{
if (!File.Exists(_configFilePath)) return new Config();
var xmlSerializer = new XmlSerializer(typeof(Config));
using (var xmlTextReader = new XmlTextReader(_configFilePath))
{
Config config = (Config)xmlSerializer.Deserialize(xmlTextReader);
return config;
}
}
}
// ...
public class Date
{
public int Year { get; set; }
public int Month { get; set; }
public int Day { get; set; }
}
Все, при чтении старой версии конфига сеттер устаревшего свойства сконвертирует данные в новый тип и присвоит их новому свойству. А при сохранении конфига добавляем атрибут XmlIgnore устаревшему свойству так, что оно больше не запишется в конфиг. В геттере устаревшего свойства вместо исключения можно производить обратную конверсию — это уже по желанию.
Плюсы:
+ нет заморочек
Минусы:
— В классе конфига остается устаревшее свойство. Атрибут Obsolete нельзя применить, т.к. в таком случае сериалайзер не будет его читать.