在我的应用程序中,我有三个存储数据的集合对象。填充这些集合的数据将从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客户端的构造函数时,我将要反序列化的数据的一个空对象作为对象参数传递 - 这是通过自定义类在异步方法之间传递的。
这是我遇到困难的地方。在事件处理程序中,我想获取字符串并将其反序列化为适当的对象。但是,尽管反序列化工作正常,但原始对象不会被修改 - 大概是因为我正在处理对象的副本。
我已经尝试将refs传递给原始构造函数和自定义类之间,但编译器不会让我将我的类型转换为“ref object”,并且我想保留web下载/反序列化代码类型不可知。另外,我有一种'感觉',我正在偏离轨道,实际上我选择的设计模式是错误的。
总而言之,创建一个'helper'类的最佳方法是什么,该类可以从适当的异步下载的xml数据字符串中填充不同类型的各种对象中的任何一个?
编辑: 添加一些进一步的上下文:我需要从异步回调中将XML字符串反序列化为对象。例如,我可能会对DownloadXMLAsync()进行三次调用,这是一个在完成后调用DownloadCompleted(DownloadCompletedEventArgs)的方法。三个调用中的每一个都返回数据以填充三个不同的对象。如何通过异步调用可靠地传递对象的引用,以便DownloadCompleted()方法可以在每种情况下正确填充正确的对象?
我试图限定DownloadXMLAsync(参照对象objectToPopulate),然后使objectToPopulate的状态对象的呼叫内HttpWebRequest.BeginGetResponse(),但我得到“无法从‘REF TicketSpaceSiteServer.CompanyList’转换到“REF对象'。”
答案 0 :(得分:2)
我使用以下代码从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);
答案 1 :(得分:0)
最后我选择了简单的选项。每当下载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;
}
}