2009-09-21 52 views
0

在我的應用程序中,我有三個用於存儲數據的集合對象。填充這些集合的數據是從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客戶端,將採取URI,下載數據,然後使用DownloadCompleteEventArgs中以字符串形式傳遞的下載數據觸發事件處理程序。當爲這個Web客戶端調用構造函數時,我將要解序列化的數據中的一個空對象作爲對象參數傳遞 - 這是通過自定義類在異步方法之間傳遞的。

這是我遇到困難的地方。在事件處理程序中,我想取出字符串並將其反序列化爲適當的對象。但是,儘管反序列化工作正常,但原始對象並未被修改 - 大概是因爲我正在處理對象的副本。

我已經嘗試將ref傳遞給原始構造函數以及自定義類之間,但編譯器不會讓我將類型轉換爲「ref object」,並且我想保留web下載/序列化代碼類型不可知的。另外,我得到了一種'感覺',我正在走上正軌,而實際上,這是我錯誤選擇的設計模式。

因此,簡言之,什麼是創造一個「助手」類,可以填充各種不同類型的對象中的任何一個從XML數據的合適的異步下載字符串的最好方法?

編輯:添加一些進一步的上下文:我需要反序列化一個XML字符串到一個異步回調對象。例如,我可能會對DownloadXMLAsync()進行三次調用,這是一個在完成時調用DownloadCompleted(DownloadCompletedEventArgs)的方法。三次調用中的每一次都返回數據以填充三個不同的對象。如何通過異步調用可靠地傳遞對象的引用,以便DownloadCompleted()方法可以在每種情況下正確地填充正確的對象?

我試圖定義DownloadXMLAsync(Ref對象objectToPopulate),然後傳遞objectToPopulate的狀態對象調用內HttpWebRequest.BeginGetResponse(),但我得到「無法從‘參考TicketSpaceSiteServer.CompanyList’轉換爲「REF目的'」。

+0

爲什麼不只是有DownloadXMLAsync返回objectToPopulate?而不是* object obj = new object; DownloadXMLAsync(ref obj); * try * object obj = DownloadXMLAsync(); *。如果您需要填充多個對象,啓動3個獨立的DownloadXMLAsync並傳入一個參數,以區分每個對象需要哪種類型,這將是最快的。 – 2009-09-22 22:22:25

+0

問題是DownloadXMLAsync在下載完成之前返回 - 因爲HTTP事務是異步執行的。 – 2009-09-24 01:10:55

回答

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; 
     } 
    } 
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); 
+0

該應用程序的反序列化部分正在工作 - 我的問題是通過異步代碼傳遞「我的」,以便一旦異步下載完成,可以填充該對象。 – 2009-09-21 22:15:38

+0

爲什麼你想填充現有的實例?包含在該例中的所有信息將在反序列化後完全被替換。如果您已經持有對現有對象的引用,是否可以將該引用更新爲新對象,而不是更新現有對象?我不知道用通用序列化信息更新已經實例化的對象的通用模式。 – 2009-09-21 22:22:55

+0

我正在填充現有實例以更新它以使其與在線數據同步。 – 2009-09-27 11:21:35