这是2008年,我仍然对这个问题感到厌烦。所以我正在开发一个Web方法,需要传递一个复杂类型并从中返回。我正在考虑的两个选项是:
传递并返回包含数据和行为的实际业务对象。运行wsdl.exe时,它将自动创建仅包含数据部分的代理类,这些代理类将自动转换为服务器端的实际业务对象。在客户端,他们只会使用哑代理类型,他们必须将它们映射到一些他们认为合适的真实业务对象。这里的一个很大的缺点是,如果我“拥有”服务器端和客户端端,并且我想使用相同的一组真实业务对象,我可能遇到一些带有名称冲突的头疼等等。(因为真实的对象和代理名称相同。)
忘记尝试传递“真正的”业务对象。相反,只需创建简单的DataTransfer对象,我将手动来回映射到我的实际业务对象。无论如何,它们仍然被wsdl.exe复制到新的代理对象,但至少我并不是在试图让自己认为Web服务本身可以处理具有业务逻辑的对象。
顺便说一下 - 有谁知道如何告诉wsdl.exe 不制作对象的副本?我们不应该只是告诉它,“嘿,在这里使用现有类型。不要复制它!”
无论如何,我现在已经确定了#2,但我很好奇你们都在想什么。我觉得有一些方式更好的方法可以做到这一点,我可能在所有方面都不完全准确,所以请让我知道你的经历是什么。
更新:我刚刚发现VS 2008在添加“服务参考”时可以选择重用现有类型,而不是在代理文件中创建全新的相同类型。甜。
答案 0 :(得分: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确实如此。
答案 1 :(得分:1)
Darren 写道:我会做混合动力。我会使用这样的对象......
有趣的想法......传递对象的序列化版本而不是(wsdl-ed)对象本身。在某种程度上,我喜欢它的优雅,但另一方面,它似乎打败了将您的Web服务暴露给潜在的第三方或合作伙伴或其他任何东西的目的。他们怎么知道要通过什么?他们是否必须完全依赖文档?它也失去了一些“异构客户端”方面,因为序列化非常.Net特定。我并不是说要批评,我只是想知道你提出的内容是否也适用于这些类型的用例。我认为在封闭环境中使用它没有任何问题。
我应该调查WCF ......我一直在避免它,但也许是时候了。
答案 2 :(得分:1)
是的,我提出的是非常具体的.NET,因为我不喜欢使用其他任何东西。我在.net之外使用webservices的唯一另一次是在javascript中,但现在我只使用json响应而不是xml webservice响应:)
答案 3 :(得分:1)
还有一个用于分隔层的参数 - 具有一组可序列化的对象,这些对象可以传递到Web服务和从Web服务传递,以及一个转换器,用于映射和转换该集合和业务对象(可能具有不适合的属性)越过电线)
它是Web服务软件工厂service factory所青睐的方法,这意味着您可以在不破坏Web服务接口/合同的情况下更改业务对象