gpt4 book ai didi

c# - 您可以将旧版本的 xml 反序列化为更新的结构吗

转载 作者:行者123 更新时间:2023-12-04 15:09:55 25 4
gpt4 key购买 nike

我正在尝试更新被反序列化的对象。取一个对象,重命名,使用零件并添加一个新对象来容纳其余对象。 .NET 中是否有一种方法可以将旧 XML 反序列化为新格式?

例如

旧结构:

<objectinfo>
<element1></element1>
<element2></element2>
<element3></element3>
<element4></element4>
</objectinfo>

新结构:

<objinfo>
<element1></element1>
<element2></element2>
</objinfo>

<newobject>
<element3></element3>
<element4></element4>
</newobject>

请注意,我正在使用 XmlSerializer 进行反序列化。

最佳答案

假设您使用的是 XmlSerializer 反序列化,如果你的 <objectinfo>是根 XML 元素的直接子元素,然后反序列化为一些 DTO类型与旧类型相同并手动或通过 映射到新对象很容易解决问题。

但是,如果被修改的对象嵌套在被反序列化的对象层次结构的深处,那么 DTO 策略就不那么方便了,因为 XmlSerializer不提供通用的代理 DTO 替换机制。在这种情况下,一种替代方法是手动处理 XmlSerializer.UnknownElement 中的未知元素。事件。

要以通用方式执行此操作,请引入以下用于 XML 反序列化的接口(interface)和扩展方法:

public interface IUnknownElementHandler
{
void OnUnknownElement(object sender, XmlElementEventArgs e);
}

public static partial class XmlSerializationHelper
{
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serializer = null)
{
serializer = serializer ?? new XmlSerializer(typeof(T)).AddUnknownElementHandler();
using (var reader = new StringReader(xmlString))
return (T)serializer.Deserialize(reader);
}

public static T LoadFromFile<T>(string filename, XmlSerializer serializer = null)
{
serializer = serializer ?? new XmlSerializer(typeof(T)).AddUnknownElementHandler();
using (var reader = new FileStream(filename, FileMode.Open))
return (T)serializer.Deserialize(reader);
}

public static XmlSerializer AddUnknownElementHandler(this XmlSerializer serializer)
{
serializer.UnknownElement += (o, e) =>
{
var handler = e.ObjectBeingDeserialized as IUnknownElementHandler;
if (handler != null)
handler.OnUnknownElement(o, e);
};
return serializer;
}
}

然后,假设您的新数据模型看起来像像这样,哪里 Root是顶级对象,ContainerType包含正在重组的元素:

[XmlRoot(ElementName = "Root")]
public class Root
{
public ContainerType ContainerType { get; set; }
}

[XmlRoot(ElementName = "ContainerType")]
public partial class ContainerType
{
[XmlElement(ElementName = "objinfo")]
public Objinfo Objinfo { get; set; }
[XmlElement(ElementName = "newobject")]
public Newobject Newobject { get; set; }
}

[XmlRoot(ElementName = "objinfo")]
public class Objinfo
{
[XmlElement(ElementName = "element1")]
public string Element1 { get; set; }
[XmlElement(ElementName = "element2")]
public string Element2 { get; set; }
}

[XmlRoot(ElementName = "newobject")]
public class Newobject
{
[XmlElement(ElementName = "element3")]
public string Element3 { get; set; }
[XmlElement(ElementName = "element4")]
public string Element4 { get; set; }
}

添加 OnUnknownElement处理程序到 ContainerType如下:

public partial class ContainerType : IUnknownElementHandler
{
#region IUnknownElementHandler Members

void IUnknownElementHandler.OnUnknownElement(object sender, XmlElementEventArgs e)
{
var container = (ContainerType)e.ObjectBeingDeserialized;

var element1 = e.Element.SelectSingleNode("element1");
var element2 = e.Element.SelectSingleNode("element2");

if (element1 != null || element2 != null)
{
container.Objinfo = container.Objinfo ?? new Objinfo();
if (element1 != null)
container.Objinfo.Element1 = element1.InnerText;
if (element2 != null)
container.Objinfo.Element2 = element2.InnerText;
}

var element3 = e.Element.SelectSingleNode("element3");
var element4 = e.Element.SelectSingleNode("element4");
if (element3 != null || element4 != null)
{
container.Newobject = container.Newobject ?? new Newobject();
if (element3 != null)
container.Newobject.Element3 = element3.InnerText;
if (element4 != null)
container.Newobject.Element4 = element4.InnerText;
}
}

#endregion
}

然后当你反序列化你的 Root 时来自使用 LoadFromFile 的文件方法如上:

var root = XmlSerializationHelper.LoadFromFile<Root>(filename);

过时的、未知的 XML 元素将由 ContainerType 进行后处理处理程序。

演示 fiddle here .

关于c# - 您可以将旧版本的 xml 反序列化为更新的结构吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65397664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com