我正在尝试将以下 XML 字符串解析为一个对象。它可以是“UpdateStructure”或“AddProcessLog”。基于类型我想把它解析成不同的对象。
这是一个显示 AddProcessLog 的 XML 示例:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Envelope>
<Header>
<Sender>MCTC</Sender>
<MacAddress>00-0C-C6-86-E4-B2</MacAddress>
</Header>
<Body>
<m:AddProcessLog xmlns:m="urn:mcsmart:machine" Version="2.1.0">
<Machine Name="MC-TC Nick" Timestamp="1683621447526">
<Active>false</Active>
<ActLineSpeed>0.000</ActLineSpeed>
<ActProductWeight>0.000</ActProductWeight>
<EventCodes />
<HasLineControl>false</HasLineControl>
<InputType>Relay</InputType>
<MaxEventType>None</MaxEventType>
<OrderNumber />
<ProductionMode>Extrusion</ProductionMode>
<Recipe />
<SetLineCapacity>-1.000</SetLineCapacity>
<SetLineSpeed>0.125</SetLineSpeed>
<SetProductWeight>1000.000</SetProductWeight>
<ActTotalExtruderCapacity>0.000</ActTotalExtruderCapacity>
<SetTotalExtruderCapacity>0.000</SetTotalExtruderCapacity>
<Group Index="0" Name="Group1">
<ActDosingTime>0.100</ActDosingTime>
<SetDosingTime>0.100</SetDosingTime>
<ActTachoVoltage>0.078</ActTachoVoltage>
<SetTachoVoltage>24.000</SetTachoVoltage>
<ShotWeight>0.100</ShotWeight>
<ActExtruderCapacity>0.000</ActExtruderCapacity>
<SetExtruderCapacity>0.028</SetExtruderCapacity>
<ActExtruderSpeed>0.000</ActExtruderSpeed>
<SetExtruderSpeed>0.000</SetExtruderSpeed>
<ActWeightCapacity>0.000</ActWeightCapacity>
<Consumption>0.000</Consumption>
<EventCodes />
<MaxEventType>None</MaxEventType>
<Unit Index="0" Name="Unit1" Type="MCPowder">
<ActMotorSpeed>0.000</ActMotorSpeed>
<BatchCounter>0</BatchCounter>
<BatchWeight>0.000</BatchWeight>
<DosingMode>Gravimetric</DosingMode>
<DosingTool>SP15</DosingTool>
<EventCodes />
<GrossWeight>0.000</GrossWeight>
<MaxEventType>None</MaxEventType>
<SetMotorSpeed>55.000</SetMotorSpeed>
<Status>Off</Status>
<Component Index="0" Name="Component1" Type="AdditiveV">
<ActCapacity>0.000</ActCapacity>
<ActDosingPercentage>0.000</ActDosingPercentage>
<BandNumber>0</BandNumber>
<Consumption>0.000</Consumption>
<Material>sp15-ng</Material>
<CorrectionFactor>1.000</CorrectionFactor>
<EventCodes />
<GranulateType>Normal</GranulateType>
<MeasurementTime>0.000</MeasurementTime>
<ActDosingWeight>0.000</ActDosingWeight>
<SetDosingWeight>0.000</SetDosingWeight>
<MaxEventType>None</MaxEventType>
<PumpType>None</PumpType>
<PumpSize>None</PumpSize>
<RegrindFillLevel>0.000</RegrindFillLevel>
<RegrindPercentage>0.000</RegrindPercentage>
<SetCapacity>0.000</SetCapacity>
<SetDosingPercentage>0.000</SetDosingPercentage>
<Tolerance>25.000</Tolerance>
<ValveType>None</ValveType>
</Component>
</Unit>
<Unit Index="1" Name="Unit2" Type="MCBalance">
<ActMotorSpeed>0.000</ActMotorSpeed>
<BatchCounter>0</BatchCounter>
<BatchWeight>0.000</BatchWeight>
<DosingMode>Gravimetric</DosingMode>
<DosingTool>GLX</DosingTool>
<EventCodes />
<GrossWeight>0.000</GrossWeight>
<MaxEventType>None</MaxEventType>
<SetMotorSpeed>0.000</SetMotorSpeed>
<Status>Off</Status>
<Component Index="0" Name="Component2" Type="AdditiveV">
<ActCapacity>0.000</ActCapacity>
<ActDosingPercentage>0.000</ActDosingPercentage>
<BandNumber>0</BandNumber>
<Consumption>0.000</Consumption>
<Material>glx-ng</Material>
<CorrectionFactor>1.000</CorrectionFactor>
<EventCodes />
<GranulateType>Normal</GranulateType>
<MeasurementTime>432.900</MeasurementTime>
<ActDosingWeight>0.000</ActDosingWeight>
<SetDosingWeight>0.000</SetDosingWeight>
<MaxEventType>None</MaxEventType>
<PumpType>None</PumpType>
<PumpSize>None</PumpSize>
<RegrindFillLevel>0.000</RegrindFillLevel>
<RegrindPercentage>0.000</RegrindPercentage>
<SetCapacity>0.015</SetCapacity>
<SetDosingPercentage>55.000</SetDosingPercentage>
<Tolerance>25.000</Tolerance>
<ValveType>None</ValveType>
</Component>
</Unit>
</Group>
<Group Index="1" Name="Group2">
<ActDosingTime>0.100</ActDosingTime>
<SetDosingTime>0.100</SetDosingTime>
<ActTachoVoltage>0.000</ActTachoVoltage>
<SetTachoVoltage>24.000</SetTachoVoltage>
<ShotWeight>0.100</ShotWeight>
<ActExtruderCapacity>0.000</ActExtruderCapacity>
<SetExtruderCapacity>0.028</SetExtruderCapacity>
<ActExtruderSpeed>0.000</ActExtruderSpeed>
<SetExtruderSpeed>0.000</SetExtruderSpeed>
<ActWeightCapacity>0.000</ActWeightCapacity>
<Consumption>0.000</Consumption>
<EventCodes />
<MaxEventType>None</MaxEventType>
<Unit Index="0" Name="Unit1" Type="MCBalance">
<ActMotorSpeed>0.000</ActMotorSpeed>
<BatchCounter>0</BatchCounter>
<BatchWeight>0.000</BatchWeight>
<DosingMode>Volumetric</DosingMode>
<DosingTool>GLX</DosingTool>
<EventCodes />
<GrossWeight>0.000</GrossWeight>
<MaxEventType>None</MaxEventType>
<SetMotorSpeed>5.000</SetMotorSpeed>
<Status>Off</Status>
<Component Index="0" Name="Component1" Type="AdditiveV">
<ActCapacity>0.000</ActCapacity>
<ActDosingPercentage>0.000</ActDosingPercentage>
<BandNumber>0</BandNumber>
<Consumption>0.000</Consumption>
<Material>glx-ng</Material>
<CorrectionFactor>1.000</CorrectionFactor>
<EventCodes />
<GranulateType>Normal</GranulateType>
<MeasurementTime>0.000</MeasurementTime>
<ActDosingWeight>0.000</ActDosingWeight>
<SetDosingWeight>0.000</SetDosingWeight>
<MaxEventType>None</MaxEventType>
<PumpType>None</PumpType>
<PumpSize>None</PumpSize>
<RegrindFillLevel>0.000</RegrindFillLevel>
<RegrindPercentage>0.000</RegrindPercentage>
<SetCapacity>0.000</SetCapacity>
<SetDosingPercentage>100.000</SetDosingPercentage>
<Tolerance>25.000</Tolerance>
<ValveType>None</ValveType>
</Component>
</Unit>
<Unit Index="1" Name="Unit2" Type="MCBalance">
<ActMotorSpeed>0.000</ActMotorSpeed>
<BatchCounter>0</BatchCounter>
<BatchWeight>0.000</BatchWeight>
<DosingMode>Gravimetric</DosingMode>
<DosingTool>GLX</DosingTool>
<EventCodes />
<GrossWeight>0.000</GrossWeight>
<MaxEventType>None</MaxEventType>
<SetMotorSpeed>0.000</SetMotorSpeed>
<Status>Off</Status>
<Component Index="0" Name="Component2" Type="AdditiveV">
<ActCapacity>0.000</ActCapacity>
<ActDosingPercentage>0.000</ActDosingPercentage>
<BandNumber>0</BandNumber>
<Consumption>0.000</Consumption>
<Material>glx-ng</Material>
<CorrectionFactor>1.000</CorrectionFactor>
<EventCodes />
<GranulateType>Normal</GranulateType>
<MeasurementTime>0.000</MeasurementTime>
<ActDosingWeight>0.000</ActDosingWeight>
<SetDosingWeight>0.000</SetDosingWeight>
<MaxEventType>None</MaxEventType>
<PumpType>None</PumpType>
<PumpSize>None</PumpSize>
<RegrindFillLevel>0.000</RegrindFillLevel>
<RegrindPercentage>0.000</RegrindPercentage>
<SetCapacity>0.000</SetCapacity>
<SetDosingPercentage>10.000</SetDosingPercentage>
<Tolerance>25.000</Tolerance>
<ValveType>None</ValveType>
</Component>
</Unit>
</Group>
</Machine>
</m:AddProcessLog>
</Body>
</Envelope>
添加进程日志:
public class ProcessLog
{
[XmlAttribute]
public string Version { get; set; }
[XmlElement(Namespace = "", ElementName = "Machine")]
public MachineLog MachineLog { get; set; }
}
更新结构:
public class UpdateStructure
{
[XmlAttribute] public string Version { get; set; }
[XmlElement(Namespace = "", ElementName = "Machine" )]
public Machine Machine { get; set; }
}
现在我得到以下异常:
---> System.InvalidOperationException: There was an error reflecting property 'Body'.
---> System.InvalidOperationException: There was an error reflecting type 'MCSmart2.Shared.Models.CommunicationModels.Body'.
---> System.InvalidOperationException: There was an error reflecting property 'UpdateStructure'.
---> System.InvalidOperationException: There was an error reflecting type 'MCSmart2.Shared.Models.CommunicationModels.UpdateStructure'.
---> System.InvalidOperationException: There was an error reflecting property 'Machine'.
---> System.InvalidOperationException: The top XML element 'Machine' from namespace '' references distinct types MCSmart2.Shared.Models.CommunicationModels.MachineLog and MCSmart2.Shared.Models.CommunicationModels.Machine. Use XML attributes to specify another XML name or namespace for the element or types.
at System.Xml.Serialization.XmlReflectionImporter.ReconcileAccessor(Accessor accessor, NameTable accessors)
at System.Xml.Serialization.XmlReflectionImporter.ReconcileLocalAccessor(ElementAccessor accessor, String ns)
at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at MCSmart.CommunicationModule.Parsers.XmlObjectParser`1.XmlToObject(Byte[] data) in C:\Users\NickdeBoerMovacolor\Movacolor\MCSmart\backend\MCSmart.CommunicationModule\Parsers\XmlObjectParser.cs:line 15
at MCSmart.CommunicationModule.Communication.Connections.MctcConnection.MctcConnection.ReadDataAsync() in C:\Users\NickdeBoerMovacolor\Movacolor\MCSmart\backend\MCSmart.CommunicationModule\Communication\Connections\MctcConnection\MctcConnection.cs:line 72
有人知道我该如何解决这个问题吗?
您没有显示
<Body>
元素的完整架构,但从您的 c# 类来看,它似乎有一个 choice 架构,其中包含两个可能的子元素之一:
<Body>
<m:AddProcessLog xmlns:m="urn:mcsmart:machine" Version="2.1.0">
<!--Contents shown in question-->
</m:AddProcessLog>
<Body>
或
<Body>
<m:UpdateStructure xmlns:m="urn:mcsmart:machine" Version="2.1.0">
<!--Contents not shown in question-->
</m:UpdateStructure>
<Body>
假设这是正确的,您可以通过为
AddProcessLog
和 UpdateStructure
引入多态类型层次结构来绑定到这样的模式,如下所示:
public abstract class BodyValueBase
{
[XmlAttribute] public string Version { get; set; }
}
[XmlRoot(ElementName="AddProcessLog", Namespace="")]
public class AddProcessLog : BodyValueBase
{
[XmlElement(ElementName="Machine")]
public MachineLog MachineLog { get; set; } // The type MachineLog is not shown in the question
}
[XmlRoot(ElementName="UpdateStructure", Namespace="")]
public class UpdateStructure : BodyValueBase
{
[XmlElement(Namespace = "", ElementName = "Machine" )]
public Machine Machine { get; set; } // The type MachineLog is not shown in the question
}
然后对应于
<Envelope>
、<Body>
和 <Header>
的根类应该如下所示:
[XmlRoot(ElementName="Body")]
public class Body
{
[XmlElement("AddProcessLog", typeof(AddProcessLog), Namespace="urn:mcsmart:machine")]
[XmlElement("UpdateStructure", typeof(UpdateStructure), Namespace="urn:mcsmart:machine")]
public BodyValueBase BodyValue { get; set; }
}
[XmlRoot(ElementName="Header")]
public class Header
{
[XmlElement(ElementName="Sender")]
public string Sender { get; set; }
[XmlElement(ElementName="MacAddress")]
public string MacAddress { get; set; }
}
[XmlRoot(ElementName="Envelope")] // The type Envelope is not shown in the question
public class Envelope
{
[XmlElement(ElementName="Header")] // The type Header is not shown in the question
public Header Header { get; set; }
[XmlElement(ElementName="Body")]
public Body Body { get; set; }
}
备注:
[XmlElement(ElementName, Type, Namespace = namespace)]
属性应用于Body.BodyValue
,一个用于BodyValueBase
的每个多态子类型,其ElementName
对应于适当的多态Type
。
有关将多态类型绑定到选择元素的文档,请参阅选择元素绑定支持:按类型区分。
另见这个答案由Marc Gravell到Using XmlSerializer to serialize derived classes有关
XmlSerializer
支持多态性的更多信息。
我将
Version
移到了基类,因为它似乎由两者共享。如果愿意,您可以将其删除并重新添加到两种派生类型中。
演示小提琴这里.