C# 反序列化同一类的备选名称

C# 反序列化同一类的备选名称,c#,xmlserializer,C#,Xmlserializer,我有一个序列器,它与以下内容并非完全不同: [Serializable] public class MSG { [XmlAttribute] public string Name { get; set; } = string.Empty; [XmlText] public string Content { get; set; } = string.Empty; } public MSG DeserializeMyMsg(string xmlstr) {

我有一个序列器,它与以下内容并非完全不同:

[Serializable]
public class MSG
{
    [XmlAttribute]
    public string Name { get; set; } = string.Empty;

    [XmlText]
    public string Content { get; set; } = string.Empty;
}

public MSG DeserializeMyMsg(string xmlstr)
{
    TextReader reader = new StringReader(xmlstr);
    var serializer = new XmlSerializer(typeof(MSG));
    MSG ret = serializer.Deserialize(reader) as MSG;
    return ret;
}
<MSG Name="woho">any content</MSG>
这将成功地反序列化以下内容:

[Serializable]
public class MSG
{
    [XmlAttribute]
    public string Name { get; set; } = string.Empty;

    [XmlText]
    public string Content { get; set; } = string.Empty;
}

public MSG DeserializeMyMsg(string xmlstr)
{
    TextReader reader = new StringReader(xmlstr);
    var serializer = new XmlSerializer(typeof(MSG));
    MSG ret = serializer.Deserialize(reader) as MSG;
    return ret;
}
<MSG Name="woho">any content</MSG>
任何内容
有时数据可能会以以下方式到达:

<Mg Name="woho">any content</Mg>
任何内容
如何将
Mg
标记为
MSG
的替代名称



味精是根。修复Mg将是长期目标,但也不是一个选项。这些消息可以用外部根进行改装。

您在评论中提到,您可以包装xml。这感觉很像黑客,但这很有效。一般来说,我的建议是不要这样做

因此,您的xml应该是:

<NewRoot><MSG Name="woho">any content</MSG></NewRoot>

您在评论中提到可以包装xml。这感觉很像黑客,但这很有效。一般来说,我的建议是不要这样做

因此,您的xml应该是:

<NewRoot><MSG Name="woho">any content</MSG></NewRoot>

好吧,仅仅修改序列化属性是不可能的。但您可以做的是引入另一种具有不同属性的类型,然后调整反序列化逻辑以选择适当的序列化程序

遗留模式:

[XmlRoot("Mg")]
public class MSGLegacyWrapper : MSG { }
反序列化逻辑:

public static MSG DeserializeMyMsg(string xmlstr)
{
    using (var reader = new StringReader(xmlstr))
    using (var xmlreader = XmlReader.Create(reader))
    using (var serializationReader = new StringReader(xmlstr))
    {
        var serializer = new XmlSerializer(typeof(MSG));
        var chosenSerializer = serializer.CanDeserialize(xmlreader)
            ? serializer 
            : new XmlSerializer(typeof(MSGLegacyWrapper));
        return chosenSerializer.Deserialize(serializationReader) as MSG;
    }
}
Ofc这可以进一步拉皮条来优化决策过程

备选方案1

如果您已经在预处理输入,那么在反序列化为强类型模型之前,您还可以使用字符串操作(ex regex)规范化根标记名

备选方案2

如果您的模式足够简单/稳定,您可以放弃基于属性的反序列化,并实现您自己的自定义
XmlReader
,它可以处理可选的根元素。请参阅文档和示例。
我相信如果性能很重要,那么这是最快的选择。

好的,仅仅修改序列化属性是不可能的。但您可以做的是引入另一种具有不同属性的类型,然后调整反序列化逻辑以选择适当的序列化程序

遗留模式:

[XmlRoot("Mg")]
public class MSGLegacyWrapper : MSG { }
反序列化逻辑:

public static MSG DeserializeMyMsg(string xmlstr)
{
    using (var reader = new StringReader(xmlstr))
    using (var xmlreader = XmlReader.Create(reader))
    using (var serializationReader = new StringReader(xmlstr))
    {
        var serializer = new XmlSerializer(typeof(MSG));
        var chosenSerializer = serializer.CanDeserialize(xmlreader)
            ? serializer 
            : new XmlSerializer(typeof(MSGLegacyWrapper));
        return chosenSerializer.Deserialize(serializationReader) as MSG;
    }
}
Ofc这可以进一步拉皮条来优化决策过程

备选方案1

如果您已经在预处理输入,那么在反序列化为强类型模型之前,您还可以使用字符串操作(ex regex)规范化根标记名

备选方案2

如果您的模式足够简单/稳定,您可以放弃基于属性的反序列化,并实现您自己的自定义
XmlReader
,它可以处理可选的根元素。请参阅文档和示例。
我相信如果性能很重要,那么这是最快的选择。

必须在班级家长那里完成。您不能有备用属性,但可以在父对象中同时具有这两个属性;您可以检查外部元素名称和补偿,或者使用上面注释中的包装器对象;但是坦率地说,您应该找到
的来源,并修复它是xml文档的根吗?如果它是一个更大的xml结构的一部分,则有一些方法可以做您想要做的事情,但如果它位于根,则没有这些方法。@TimRutter MSG是根,但xml被去除了名称空间和xml文档信息。因此,在解析之前包装它是可能的<代码>$“{str}”必须在类的父级完成。您不能有备用属性,但可以在父对象中同时具有这两个属性;您可以检查外部元素名称和补偿,或者使用上面注释中的包装器对象;但是坦率地说,您应该找到
的来源,并修复它是xml文档的根吗?如果它是一个更大的xml结构的一部分,则有一些方法可以做您想要做的事情,但如果它位于根,则没有这些方法。@TimRutter MSG是根,但xml被去除了名称空间和xml文档信息。因此,在解析之前包装它是可能的
$“{str}”
我发现了更多不兼容的内容,因此我将按照您的答案和其他多条评论中给出的建议进行操作,只是不这样做。我将声明我的软件与Mg消息不兼容。也许最好的答案是,它仍然显示了使用xml序列化可以做的事情,值得保留。您还可以做其他事情,例如定制序列化程序,这可能值得研究。我发现了更多不兼容的地方,因此我将遵循您的答案和其他多个注释中给出的建议,只是不这样做。我将声明我的软件与Mg消息不兼容。也许最好的答案是,它仍然显示了使用xml序列化可以做的事情,值得保留。您还可以做其他事情,例如定制序列化程序,这可能值得研究。