2009-09-21 2 views
0

내 애플리케이션에는 데이터를 저장하는 세 개의 수집 객체가 있습니다. 이러한 콜렉션을 채우는 데이터는 웹의 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; } 
    } 
} 

, 내가 걸릴 것입니다 비동기 웹 클라이언트를 작성했습니다 :

세 가지 데이터 클래스

다음은 전형적인 예입니다, 매우 간단 URI를 사용하여 데이터를 다운로드 한 다음 DownloadCompleteEventArgs 내에 문자열로 전달 된 다운로드 한 데이터로 이벤트 처리기를 시작합니다. 이 웹 클라이언트의 생성자를 호출 할 때 비어있는 객체 중 하나를 데이터에 대한 직렬화를 객체 매개 변수로 전달합니다. 이는 비공개 클래스를 통해 비동기 메소드간에 전달됩니다.

여기가 내가 힘들어하고 있습니다. 이벤트 처리기에서 문자열을 가져 와서 해당 개체로 역 직렬화합니다. 그러나 역 직렬화가 잘 작동하더라도 원본 객체는 수정되지 않습니다. 아마도 객체의 복사본을 작업하고 있기 때문입니다.

원본 생성자와 사용자 지정 클래스간에 참조를 전달하려고했지만 컴파일러에서 내 형식을 "ref 개체"로 캐스팅하지 못하게하고 웹 다운로드/직렬화 코드 유형 불가지론 자. 또한, 나는 궤도에서 벗어나는 '느낌'을 얻고 있으며 실제로는 잘못한 디자인 패턴의 선택입니다.

요약하면 비동기 적으로 다운로드 된 xml 데이터 문자열에서 다양한 유형의 다양한 개체 중 하나를 채울 수있는 '도우미'클래스를 만드는 가장 좋은 방법은 무엇입니까?

편집 :몇 가지 더 컨텍스트를 추가 : 내가 비동기 콜백에서 객체로 XML 문자열을 역 직렬화 할 필요가있다. 예를 들어 DownloadXMLAsync()를 세 번 호출 할 수 있습니다.이 작업은 완료되면 DownloadCompleted (DownloadCompletedEventArgs)를 호출하는 메서드입니다. 세 개의 호출은 각각 데이터를 리턴하여 세 개의 다른 오브젝트를 채 웁니다. 어떻게 비동기 호출을 통해 객체에 대한 참조를 안정적으로 전달하여 DownloadCompleted() 메서드가 각각의 경우에 올바른 객체를 올바르게 채울 수 있습니까?

I 다음은 HttpWebRequest.BeginGetResponse()를 호출 내 상태 객체의 objectToPopulate를 전달 DownloadXMLAsync (참조 객체 objectToPopulate)를 정의하는,하지만 난 심판 '에'심판 TicketSpaceSiteServer.CompanyList '에서 변환 할 수 없습니다 "얻을 시도 목적'".

+0

은 왜 그냥 DownloadXMLAsync는 objectToPopulate를 반환했다? * object 대신에 obj = new object; DownloadXMLAsync (ref obj); * try * object obj = 다운로드 XMLAssembly(); *. 여러 객체를 채워야하는 경우 3 개의 별도 DownloadXMLAsync를 시작하고 각각에 대해 원하는 유형을 구분하는 매개 변수를 전달하는 것이 가장 빠릅니다. –

+0

문제는 HTTP 트랜잭션이 비동기 적으로 수행되므로 DownloadXMLAsync가 다운로드가 완료되기 전에 반환된다는 것입니다. –

답변

0

:

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; 
    } 
} 

처럼 사용합니다. DownloadCompleted async 콜백은 XML 파일을 다운로드 할 때마다 호출됩니다. 채울 개체에 대한 참조를 전달하지 않지만 대신 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 문자열에서 새 개체를 생성하려면 다음 코드를 사용 : 나는 간단한 옵션에 들어갑니다 결국

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

응용 프로그램의 deserialization 부분이 작동합니다. 내 문제는 비동기 코드를 통해 "my"를 전달하여 비동기 다운로드가 완료되면 개체를 채울 수 있도록합니다. –

+0

기존 인스턴스를 채우려하는 이유가 무엇입니까? 해당 인스턴스에 포함 된 모든 정보는 직렬화 복원 후에 완전히 대체됩니다. 기존 객체에 대한 참조를 이미 보유하고있는 경우 기존 객체를 제자리에 업데이트하지 않고 해당 참조를 새 객체로 업데이트 할 수 있습니까? 직렬화 된 정보로 이미 인스턴스화 된 객체를 업데이트하는 일반 패턴을 인식하지 못합니다. –

+0

온라인 데이터와 동기화되도록 기존 인스턴스를 업데이트하려고합니다. –

관련 문제