我有
public bool Included { get; set; }
我想改为:
public bool IsIncluded { get; set; }
我希望具有向后兼容性。我想只在代码中定义IsIncluded,但能够读取旧的xml,其中属性将是“包含”。
XmlSerializer是否支持它以及如何支持?
注意:我尝试没有成功......(不反序列化)
public bool IsIncluded { get; set; }
[Obsolete]
public bool Included
{
set { IsIncluded = value; }
get { return IsIncluded; }
}
更新我只想补充一点,我更喜欢我的解决方案,因为我希望我的xml成为IsIncluded,对我来说更合适。像我一样(下面的解决方案),将使我能够更改xml,但保持以前的版本正常工作。从长远来看,我可能会删除代码以支持旧版本。
更新2018-02-01 请在下面的解决方案和建议的解决方案中查看Greg Petersen的评论。他提出了一个很好的解决方案,以便将校正封装在应该完成的地方(类)。 WOW !!!
答案 0 :(得分:3)
试试:
[XmlElement("Included")]
public bool IsIncluded { get; set; }
实施例。 v1.c的序列化和v2.c的反序列化:
namespace v1
{
public class c
{
public bool Included { get; set; }
}
}
namespace v2
{
public class c
{
[XmlElement("Included")]
public bool IsIncluded { get; set; }
}
}
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
StringWriter sw = new StringWriter();
new XmlSerializer(typeof(v1.c)).Serialize(sw, new v1.c{ Included=true} );
StringReader sr = new StringReader( sw.ToString() );
v2.c cc = (v2.c)new XmlSerializer(typeof(v2.c)).Deserialize(sr);
Debug.Assert(cc.IsIncluded);
}
}
}
答案 1 :(得分:2)
我找到了。这就是我做到的。
// ******************************************************************
public static SimulScenario LoadFromFile(string path)
{
if (!File.Exists(path))
{
return new SimulScenarioError(path);
}
SimulScenario simulScenario = null;
XmlTextReader reader = new XmlTextReader(path);
XmlSerializer x = new XmlSerializer(typeof(SimulScenario));
x.UnknownAttribute +=x_UnknownAttribute;
x.UnknownElement += x_UnknownElement;
x.UnknownNode += x_UnknownNode;
x.UnreferencedObject += x_UnreferencedObject;
try
{
simulScenario = (SimulScenario)x.Deserialize(reader);
}
catch (Exception)
{
return new SimulScenarioError(path);
}
finally
{
reader.Close();
}
return simulScenario;
}
static void x_UnreferencedObject(object sender, UnreferencedObjectEventArgs e)
{
}
static void x_UnknownNode(object sender, XmlNodeEventArgs e)
{
}
static void x_UnknownElement(object sender, XmlElementEventArgs e)
{
var simulChangeState = e.ObjectBeingDeserialized as SimulChangeState;
if (simulChangeState != null)
{
if (e.Element.Name == "Included")
{
bool val;
if (bool.TryParse(e.Element.InnerText, out val))
{
simulChangeState.IsIncluded = val;
}
else
{
throw new FileFormatException(Log.Instance.AddEntry(LogType.LogError, "Invalid scenario file format."));
}
}
}
}
static void x_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
}
答案 2 :(得分:1)
我使用Eric的解决方案进行了一些修改。我添加了一个接口类来处理向后兼容性部分。
public interface IBackwardCompatibilitySerializer
{
void OnUnknownElementFound(string uknownName, string value);
}
使用这个,我们只需要像这样编写一次未知元素事件
private static void x_UnknownElement(object sender, XmlElementEventArgs e)
{
var deserializedObj = (e.ObjectBeingDeserialized as IBackwardCompatibilitySerializer);
if (deserializedObj == null) return;
deserializedObj.OnUnknownElementFound(e.Element.Name, e.Element.InnerText);
}
然后,对于要更改变量名的任何类,让它实现接口。你的课程看起来像这样
public class MyClass : IBackwardCompatibilitySerializer
{
// public bool Included { get; set; } Old variable
public bool IsIncluded { get; set; } // New Variable
public void OnUnknownElementFound(string unknownElement, string value)
{
switch(unknownElement)
{
case "Included":
IsIncluded = bool.Parse(value);
return;
}
}
}
Eric,如果您愿意,可以随意将其纳入您的解决方案。