[英]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.