2008-08-16 86 views
9

現在是2008年,我仍然在這一個。所以我正在開發一個web方法,它需要一個傳入它並從它返回的複雜類型。這兩個選項,我有玩弄有:通過Web服務發送複雜數據的首選方法是什麼?

  1. 傳遞和返回實際業務對象與數據和行爲。當運行wsdl.exe時,它將自動創建僅包含數據部分的代理類,並且這些類將自動轉換爲服務器端的真實業務對象,並從中自動轉換。在客戶端,他們只會使用啞代理類型,他們將不得不將它們映射到一些他們認爲合適的真實業務對象。這裏的一大缺點是,如果我「擁有」了服務器和客戶端,並且我想使用同一組真實的業務對象,那麼我會遇到名稱衝突等問題。(因爲真實對象和代理被命名爲相同)。

  2. 忘記試圖通過「真實」業務對象。相反,只需創建簡單的DataTransfer對象,我將手動來回映射到真實的業務對象。無論如何,它們仍然通過wsdl.exe複製到新的代理對象,但至少我並不是在欺騙自己,認爲Web服務本身可以處理帶有業務邏輯的對象。

順便說一句 - 有誰知道如何告訴Wsdl.exe用至使對象的副本?我們不應該只是說出來,「嘿,在這裏使用這種現有的類型,不要複製它!」

無論如何,我現在已經定了2號,但我很好奇你們都在想什麼。我有一種感覺,的方式更好的方式來做到這一點,我可能不完全準確的所有我的觀點,所以請讓我知道你的經歷是什麼。

更新:我剛剛發現VS 2008有一個選項,可以在添加「服務參考」時重新使用現有類型,而不是在代理文件中創建全新的相同類型。甜。

回答

1

還有一個用於分隔層的參數 - 有一組可序列化的對象被傳遞到Web服務和翻譯器以在該集合和業務對象之間進行映射和轉換(其可能具有不適合通過線路的屬性)

其被Web服務軟件工廠青睞的方法service factory並且意味着您可以在不破壞Web服務接口/合同的情況下更改您的業務對象

4

我會做一個混合。我會使用這樣的對象

public class TransferObject 
{ 
    public string Type { get; set; } 
    public byte[] Data { get; set; } 
} 

然後我有一個很好的小工具,序列化一個對象,然後壓縮它。

public static class CompressedSerializer 
{ 
    /// <summary> 
    /// Decompresses the specified compressed data. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="compressedData">The compressed data.</param> 
    /// <returns></returns> 
    public static T Decompress<T>(byte[] compressedData) where T : class 
    { 
     T result = null; 
     using (MemoryStream memory = new MemoryStream()) 
     { 
      memory.Write(compressedData, 0, compressedData.Length); 
      memory.Position = 0L; 

      using (GZipStream zip= new GZipStream(memory, CompressionMode.Decompress, true)) 
      { 
       zip.Flush(); 
       var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
       result = formatter.Deserialize(zip) as T; 
      } 
     } 

     return result; 
    } 

    /// <summary> 
    /// Compresses the specified data. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="data">The data.</param> 
    /// <returns></returns> 
    public static byte[] Compress<T>(T data) 
    { 
     byte[] result = null; 
     using (MemoryStream memory = new MemoryStream()) 
     { 
      using (GZipStream zip= new GZipStream(memory, CompressionMode.Compress, true)) 
      { 
       var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
       formatter.Serialize(zip, data); 
      } 

      result = memory.ToArray(); 
     } 

     return result; 
    } 
} 

然後,您只需傳遞將具有類型名稱的傳輸對象。所以,你可以做這樣的事情

[WebMethod] 
public void ReceiveData(TransferObject data) 
{ 
    Type originType = Type.GetType(data.Type); 
    object item = CompressedSerializer.Decompress<object>(data.Data); 
} 

現在壓縮串行使用泛型,使它強類型的,但你可以做很容易的方法採取的Type對象使用上述originType反序列化,一切都取決於你實現。

希望這給你一些想法。哦,並回答你的其他問題,wsdl.exe不支持重用類型,WCF雖然。

+0

謝謝!在處理zip流之後,我注意到您讀取了內存流**之後,我無法進行壓縮工作。顯然沖洗拉鍊流是不夠的... – dotjoe 2010-02-05 22:15:25

1

Darren寫道:我會做一個混合。我會使用這樣的對象...

有趣的想法...傳遞對象的序列化版本而不是(wsdl-ed)對象本身。在某種程度上,我喜歡它的優雅,但換一種說法,它似乎打破了將Web服務暴露給潛在的第三方或合作伙伴或其他任何目的的目的。他們怎麼知道要傳遞什麼?他們是否必須純粹依靠文檔?它也失去了一些「異類客戶端」的方面,因爲序列化非常特定於.Net。我並不意味着要批評,我只是想知道你所提議的內容是否也適用於這些類型的用例。儘管如此,在封閉的環境中使用它並沒有什麼問題。

我應該看看WCF ......我一直在避免它,但也許是時候了。

1

哦,當然,我只做這個時,我是Web服務的消費者,或者如果你有某種控制器,他們請求一個對象,然後你處理序列化和發送,而不是直接消費網絡服務。但實際上,如果他們直接使用Web服務,那麼他們不需要或者必須擁有首先具有類型的程序集,並且應該使用wsdl生成的對象。

是的,我提出的是非常特定於.NET的,因爲我不喜歡使用其他任何東西。唯一一次我在.net之外使用webservices的時候是在javascript中,但現在我只使用json響應而不是xml webservice響應:)

相關問題