代码之家  ›  专栏  ›  技术社区  ›  jeremcc chris

通过web服务发送复杂数据的首选方法是什么?

  •  9
  • jeremcc chris  · 技术社区  · 16 年前

    现在是2008年,我仍然为这件事感到难过。所以我正在开发一个web方法,它需要一个复杂的类型传入并从中返回。我正在考虑的两个选项是:

    1. 往返 真实的 具有数据和行为的业务对象。当wsdl.exe运行时,它将自动创建只包含数据部分的代理类,并且这些代理类将在服务器端自动转换为我的真实业务对象。在客户端,他们只能使用哑代理类型,并且必须将它们映射到他们认为合适的一些真实业务对象中。这里的一个大缺点是,如果我“拥有”服务器端和客户端,并且我想要使用同一组真实的业务对象,我可能会遇到名称冲突等问题(因为真实对象和代理的名称相同)

    2. 忘记尝试传递“真实”业务对象。相反,只需创建简单的数据传输对象,我将手动来回映射到真实的业务对象。不管怎样,它们仍然会被wsdl.exe复制到新的代理对象中,但至少我没有欺骗自己,让自己认为web服务可以以本机方式处理包含业务逻辑的对象。

    复制对象?难道我们不应该告诉它,“嘿,使用这里现有的类型,不要复制它!”

    方法 一般来说,更好的方法可以做到这一点,我甚至可能不能完全准确地表达我的观点,所以请让我知道你的经历。

    :我刚刚发现VS 2008在添加“服务引用”时可以重用现有类型,而不是在代理文件中创建全新的相同类型。含糖的

    4 回复  |  直到 16 年前
        1
  •  4
  •   Darren Kopp    16 年前

    我会做混合动力车。我会用这样的物体

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

    现在,压缩序列化程序使用泛型使其成为强类型,但是您可以使用上面的originType使方法轻松地接受类型对象以进行反序列化,这一切都取决于您的实现。

    希望这能给你一些想法。哦,为了回答您的另一个问题,wsdl.exe不支持重用类型,但WCF支持。

        2
  •  1
  •   jeremcc chris    16 年前

    戴伦

    有趣的想法。。。传递对象的序列化版本,而不是(wsdl)对象本身。在某种程度上,我喜欢它的优雅,但在另一方面,它似乎违背了向潜在的第三方或合作伙伴或其他人公开web服务的目的。他们怎么知道该通过什么?他们是否必须完全依赖文件?它还丢失了一些“异构客户端”特性,因为序列化是特定于.Net的。我并不想批评你,我只是想知道你的建议是否也适用于这些类型的用例。不过,我认为在封闭环境中使用它没有任何问题。

        3
  •  1
  •   Darren Kopp    16 年前

    是的,我提出的是非常特定于.NET的,因为我不喜欢使用其他任何东西。我在.net之外使用Web服务的唯一其他时间是在javascript中,但现在我只使用json响应而不是xml Web服务响应:)

        4
  •  1
  •   Rahul Patel user2885077    9 年前

    还有一个用于分离层的参数-有一组可串行化的对象(从web服务传递到web服务)和一个转换器(在该组对象和业务对象之间进行映射和转换)(可能具有不适合通过连接传递的属性)

    这是web服务软件工厂喜欢的方法 service factory 这意味着您可以在不破坏web服务接口/契约的情况下更改业务对象