Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#将XML响应映射到未知类_C#_Xml_Generics_Reflection_Xml Serialization - Fatal编程技术网

C#将XML响应映射到未知类

C#将XML响应映射到未知类,c#,xml,generics,reflection,xml-serialization,C#,Xml,Generics,Reflection,Xml Serialization,我试图实现一个通用的解决方案,用于通过任何方式(IP、串行文本文件等)发送和接收XML 在我得到响应字符串之前,所有这些看起来都正常工作 我需要做的是将此响应类型转换为正确的类类型(LoginResponse、LogoffResponse、CardPaymentResponse) 等等 我无法找到一种通用的方法来以有效的方式将此XMl转换回对象 以下是我目前得到的信息: 响应字符串示例: 用于LoginResponse的XML: <?xml version="1.0" encoding="

我试图实现一个通用的解决方案,用于通过任何方式(IP、串行文本文件等)发送和接收XML

在我得到响应字符串之前,所有这些看起来都正常工作

我需要做的是将此响应类型转换为正确的类类型(LoginResponse、LogoffResponse、CardPaymentResponse) 等等

我无法找到一种通用的方法来以有效的方式将此XMl转换回对象

以下是我目前得到的信息:

响应字符串示例:

用于LoginResponse的XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<ServiceResponse RequestType="Login" ApplicationSender="POSsel01"     WorkstationID="1" RequestID="1254" ProtocolVersion="000000001234" DeviceType="113" SWChecksum="AC3F" CommunicationProtocol="000000000432" Model="011" ApplicatioSoftwareVersion="000000000100" Manufacturer_Id="023" OverallResult="Success" xmlns="http://www.nrf-arts.org/IXRetail/namespace" xmlns:IFSF="http://www.ifsf.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nrf-arts.org/IXRetail/namespace C:\Schema\ServiceResponse.xsd"/>
ServiceResponse类型,此处没有其他字段

public class ServiceResponse : IFSFResponseBase
{

}
public class CardServiceResponse : IFSFResponseBase
{
    [XmlElement("Terminal")]
    public CardServiceResponseTerminal Terminal
    { get; set; }

    [XmlElement("Tender")]
    public CardServiceResponseTender Tender
    {
        get; set;
    }
}
CardServiceResponse类型,此处为公共字段

public class ServiceResponse : IFSFResponseBase
{

}
public class CardServiceResponse : IFSFResponseBase
{
    [XmlElement("Terminal")]
    public CardServiceResponseTerminal Terminal
    { get; set; }

    [XmlElement("Tender")]
    public CardServiceResponseTender Tender
    {
        get; set;
    }
}
CardServiceResponse帮助程序类

public class CardServiceResponseTerminal
{
    [XmlAttribute()]
    public string TerminalID { get; set; }

    [XmlAttribute()]
    public string TerminalBatchField { get; set; }

    [XmlAttribute()]
    public string STANField { get; set; }

}

public class CardServiceResponseTender
{
    [XmlElement("TotalAmount")]
    public CardServiceResponseTenderTotalAmount TotalAmount { get; set; }
}

public class CardServiceResponseTenderTotalAmount
{
    private string valueField;

    [XmlAttribute()]
    public string CashBackAmount
    {
        get;
        set;
    }

    [XmlAttribute()]
    public string Currency
    {
        get;
        set;
    }

    [XmlText()]
    public string Value
    {
        get
        {
            return this.valueField;
        }
        set
        {
            this.valueField = value;
        }
    }
}
具体LogoffResponse类,无其他字段

[XmlRoot("ServiceResponse")]
public class LogoffResponse : ServiceResponse
{

}
[XmlRoot("CardServiceResponse")]
public class CardPaymentResponse : CardServiceResponse
{

}
具体LoginResponse类,处理额外字段

[XmlRoot("ServiceResponse")]
public class LoginResponse : ServiceResponse
{
    [XmlAttribute()]
    public string POPID { get; set; }

    [XmlAttribute()]
    public string ReferenceNumber { get; set; }

    [XmlAttribute()]
    public string ProtocolVersion { get; set; }

    [XmlAttribute()]
    public string DeviceType { get; set; }

    [XmlAttribute()]
    public string SWChecksum { get; set; }

    [XmlAttribute()]
    public string CommunicationProtocol { get; set; }

    [XmlAttribute()]
    public string Model { get; set; }

    [XmlAttribute()]
    public string ApplicatioSoftwareVersion { get; set; }

    [XmlAttribute()]
    public string Manufacturer_Id { get; set; }

}
具体的CardPaymentResponse类,无其他字段

[XmlRoot("ServiceResponse")]
public class LogoffResponse : ServiceResponse
{

}
[XmlRoot("CardServiceResponse")]
public class CardPaymentResponse : CardServiceResponse
{

}
具体的CardPaymentReturnResponse类,需要一些额外的数据

[XmlRoot("CardServiceResponse")]
public class CardPaymentRefundResponse : CardServiceResponse
{
    [XmlAttribute()]
    public string ExtraValue { get; set; }
}
用于从响应中删除名称空间的帮助器类

public class NamespaceIgnorantXmlTextReader : XmlTextReader
{
    public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader) : base(reader) { }

    public override string NamespaceURI
    {
        get { return ""; }
    }
}
对于下面的代码,在解析之前,我不知道将收到的实际响应,所以我不知道 知道我可以用什么来代替具体类(在本例中是ServiceResponse)

这对于注销响应类型来说很好,但如果它是LoginResponse类型就不行了

因此,我可以使用LoginResponse,但如果响应是CardServiceResponse,则会出现异常并失败 因为根元素不是SERVICERESPONSE,而是CardServiceResponse

try
{
    XmlSerializer serializer = new XmlSerializer(typeof(LoginResponse));

    StringReader sr = new StringReader(XMLResponse);

    NamespaceIgnorantXmlTextReader XMLWithoutNamespace = new NamespaceIgnorantXmlTextReader(sr);

    return (LoginResponse)serializer.Deserialize(XMLWithoutNamespace);

}
catch (Exception ex)
{
    //Breakpoint code here for debugging ATM, To BE REMOVED
    throw;
}
我尝试了下面的方法,它会起作用,但我想知道是否有更好的方法来实现这一点

private object InternalParse(string sXML)
    {
        object oRetVal = null;

        try
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(sXML);
            XmlNode ReqType = xmlDoc.DocumentElement.Attributes.GetNamedItem("RequestType");

            Assembly asm = Assembly.GetExecutingAssembly();

            Type type = asm.GetType(asm.GetName().Name + "." + ReqType.Value + "Response");

            object instance = null;

            try
            {
                instance = (object)Activator.CreateInstance(type);
            }
            catch
            {
                //problem creating type from RequestType Name + Response appended on, the class
                //probably does not exist. Lets create the parent class
                type = asm.GetType(asm.GetName().Name + "." + xmlDoc.DocumentElement.Name);
                instance = (object)Activator.CreateInstance(type);
            }

            XmlSerializer serializer = new XmlSerializer(instance.GetType());

            StringReader sr = new StringReader(sXML);

            NamespaceIgnorantXmlTextReader XMLWithoutNamespace = new NamespaceIgnorantXmlTextReader(sr);

            oRetVal = serializer.Deserialize(XMLWithoutNamespace);
        }
        catch (Exception ex)
        {
            //Log ex here
        }

        return oRetVal;
    }

提前感谢

找人阅读这么多代码很难。我听到了,但如果不至少显示这么多代码,就很难表达我想要的内容,我加载了更多的代码,我遗漏了这些代码只是为了表达问题的要点,基本上我检查XML字符串以确定要反序列化的类类型是否正确,反射是否过火了?更有效的方法??这看起来很合理,但是您可能会切换到更新的API。1) 使用
NamespaceIgnorantXmlTextReader将xml字符串加载到
XDocument
;2) 从
doc.Root.Name
确定对象类型;3) 按照此处的指定直接反序列化
XDocument