现在已经是 2008 年了,我仍然对这件事心有余悸。因此,我正在开发一个 Web 方法,需要将复杂类型传递给它并从中返回。我正在考虑的两个选项是:

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

  2. 忘记尝试传递“真实的”业务对象。相反,只需创建简单的 DataTransfer 对象,我将手动将其来回映射到我的真实业务对象。无论如何,它们仍然会被 wsdl.exe 复制到新的代理对象,但至少我没有欺骗自己认为 Web 服务可以本机处理带有业务逻辑的对象。

顺便说一句 - 有谁知道如何告诉 wsdl.exe 不是 复制该对象?难道我们不应该直接告诉它:“嘿,使用这里现有的类型。别抄袭!”

不管怎样,我现在已经选择了#2,但我很好奇你们都怎么想。我有一种感觉 方式 一般来说,更好的方法可以做到这一点,我什至可能无法完全准确地表达我的所有观点,所以请让我知道您的经历。

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

有帮助吗?

解决方案

还有一个关于分离层的争论 - 拥有一组可序列化的对象,这些对象可以传入和传出 Web 服务,并有一个转换器来在该集合和业务对象之间进行映射和转换(这些对象可能具有不适合传递的属性)金属丝)

这是网络服务软件工厂所青睐的方法 服务工厂 意味着您可以在不破坏 Web 服务接口/合同的情况下更改业务对象

其他提示

我会做一个混合动力。我会使用这样的对象

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 支持。

达伦 写道:我会做一个混合动力。我会使用这样的对象......

有趣的想法...传递对象的序列化版本而不是(wsdl-ed)对象本身。在某种程度上,我喜欢它的优雅,但在另一方面,它似乎违背了将你的网络服务暴露给潜在的第三方或合作伙伴或其他什么的目的。他们怎么知道要传递什么?他们是否必须完全依赖文档?它还失去了一些“异构客户端”方面,因为序列化是非常特定于 .Net 的。我并不是要批评,我只是想知道您所提议的内容是否也适用于这些类型的用例。不过,我不认为在封闭环境中使用它有什么问题。

我应该看看WCF...我一直在回避它,但也许是时候了。

哦,当然,我只在我是 Web 服务的使用者时才这样做,或者如果您有某种控制器,他们从中请求对象,然后您处理序列化和发送,而不是他们直接使用 Web 服务。但实际上,如果他们直接使用 Web 服务,那么他们就不需要或不一定拥有包含该类型的程序集,并且应该使用 wsdl 生成的对象。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top