2008-08-16 52 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响应:)

相关问题