繁体   English   中英

从异步接收的数据中反序列化

[英]Deserializing from data received asynchronously

在我的应用程序中,我有三个用于存储数据的集合对象。 填充这些集合的数据是从Web上的XML文件下载的。

这三个数据类非常简单,以下是一个典型示例:

[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "companies")]
public partial class CompanyList
{      
    private List<Company> itemsField = new List<Company>();

    [XmlElement("company", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public List<Company> Items
    {
        get { return this.itemsField; }
    }
}

[SerializableAttribute()]
[XmlTypeAttribute(AnonymousType = true)]
public partial class Company
{
    private int companyIdField;
    private string companyNameField;

    [XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, ElementName = "companyid")]
    public int CompanyID
    {
        get { return this.companyIdField; }
        set { this.companyIdField = value; }
    }

    [XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, ElementName = "companyname")]
    public string CompanyName
    {
        get { return this.companyNameField; }
        set { this.companyNameField = value; }
    }
}

为了从Web下载这些对象的数据,我编写了一个异步Web客户端,该客户端将获取URI,下载数据,然后使用在DownloadCompleteEventArgs中作为字符串传递的已下载数据触发事件处理程序。 在为该Web客户端调用构造函数时,我将要反序列化的数据的空对象之一作为对象参数传递-通过自定义类在异步方法之间传递。

这是我遇到困难的地方。 在事件处理程序中,我想获取字符串并将其反序列化为适当的对象。 但是,尽管反序列化工作正常,但原始对象并未修改-大概是因为我正在处理该对象的副本。

我尝试将ref传递到原始构造函数和自定义类之间,但是编译器不允许我将类型强制转换为“ ref object”,并且我想保持Web下载/反序列化代码的类型-不可知。 另外,我有一种“感觉”,这使我偏离了轨道,这实际上是我对设计模式的选择所造成的错误。

因此,总而言之,创建一个“帮助程序”类的最佳方法是什么,该类可以从合适的异步下载的xml数据字符串中填充各种不同类型的对象中的任何一个?

编辑: 添加更多的上下文:我需要将XML字符串从异步回调反序列化为对象。 例如,我可能对DownloadXMLAsync()进行了三个调用,该方法是在完成后调用DownloadCompleted(DownloadCompletedEventArgs)的方法。 三个调用中的每一个都返回数据以填充三个不同的对象。 如何通过异步调用可靠地传递对对象的引用,以便在每种情况下DownloadCompleted()方法都能正确填充正确的对象?

我尝试定义DownloadXMLAsync(ref object objectToPopulate),然后在调用HttpWebRequest.BeginGetResponse()的状态对象中将objectToPopulate传递给,但是我得到“无法从ref TicketSpaceSiteServer.CompanyList转换为ref object”。

我使用以下代码从XML字符串构造新对象:

public class Util
{
    static private T Load<T>(string xml)
    {
        T t;

        XmlSerializer serializer = new XmlSerializer(typeof(T));
        try
        {
            System.Text.ASCIIEncoding  encoding=new System.Text.ASCIIEncoding();
            Byte[] bytes = encoding.GetBytes(xml);
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                t = (T)serializer.Deserialize(ms);
            }
        }
        catch (Exception ex) 
        {
            throw ex; // This part is for debugging
        }

        return t;
    }
}

像这样使用它:

MyType my = Util.Load<MyType>(myXmlString);

最后,我选择了简单的方法。 每当下载XML文件时,都会调用DownloadCompleted异步回调。 我没有传递要填充的对象的引用,而是解析XML以找出其中包含哪个对象的数据,然后使用该知识正确返回正确类型的对象,即

        if (xml.StartsWith("<?xml version=\"1.0\"?>\n<companies>"))
        {
            return LoadFromXmlString<CompanyList>(xml);
        }
        else if (xml.StartsWith("<?xml version=\"1.0\"?>\n<shows>"))
        {
            return LoadFromXmlString<ShowList>(xml);
        }
        else if (xml.StartsWith("<?xml version=\"1.0\"?>\n<performances>"))
        {
            return LoadFromXmlString<PerformanceList>(xml);
        }

然后,在父类中:

    void wd_DownloadComplete(object sender, DownloadCompletedEventArgs e)
    {
        object foo = SerializationHelper.LoadFromXmlString(e.DownloadedString);
        switch (foo.GetType().ToString())
        {
            case "TicketSpaceSiteServer.CompanyList":
                companies = foo as CompanyList;
                break;
            case "TicketSpaceSiteServer.PerformanceList":
                performances = foo as PerformanceList;
                break;
            case "TicketSpaceSiteServer.ShowList":
                shows = foo as ShowList;
                break;
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM