如何使用Web服务返回自定义对象

时间:2009-09-24 03:01:47

标签: c# web-services .net-1.1

[问题]
创建了要部署在服务器计算机和客户端计算机上的共享库,如何在客户端服务器与库提供的类之间进行通信?

通过webservices传输信息似乎不起作用,因为Web服务返回的序列化对象是一个不转换为共享库的Web服务类。

我是否错误地使用了网络服务?还有更好的方法吗?

[示例]

MyLibrary.cs和SubLibrary.cs位于客户端应用程序使用的共享程序集中。

MyLibrary.cs

public class MyLibrary
{
    private SubLibrary sublib = new SubLibrary();

    public class MyLibrary()
    {
    }

    public string GetValue()
    {
        return sublib.GetValue();
    }
}

SubLibrary.cs

public class SubLibrary
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }
}

WebService.asmx.cs

[WebMethod]
public MyLibrary GetInfo()
{
    return new MyLibrary();
}

客户端应用

private void GetInfo_Click(object sender, System.EventArgs e)
{
  WS.WebService services = new WS.WebService();

  MyLibrary info = services.GetInfo();  // This of course doesn't convert.

  MessageBox.Show(info.GetValue());
}

3 个答案:

答案 0 :(得分:5)

简而言之,这是1.1的痛苦(部分也是2.0)。仅真正的程序集共享(或类型共享)开始成为WCF(.NET 3.0)中的一项功能。 1.1中生成的代理永远不会直接与“实际”类兼容;您可以在多个服务(“sharetypes”?)之间共享相同的代理,但不能与独立的源文件IIRC共享。

由于它是C#1.2,你既没有部分类也没有扩展方法来欺骗它们。

选项(我可以看到):

  • 编写静态实用工具方法,在两个对象模型之间进行费力的翻译
  • 同上,但使用XmlSerializer(代码少,但速度不快)
  • 和它一起生活
  • 升级到WCF(非常重大的变化)

答案 1 :(得分:1)

使用Web服务,您通过线路发送的每个对象的类型必须是可序列化的。您可以通过实现IXmlSerializable接口使SubLibrary可序列化。

public class SubLibrary : IXmlSerializable 
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        //...
    }

    public void WriteXml(XmlWriter writer)
    {
        //...
    }
}

但有一点需要注意:由于您通过WS传递了MyLibrary和SubLibrary,因此需要确保它们都是可序列化的。此外,由于您正在传递MyLibrary并且包含 SubLibrary的实例,因此您必须在序列化期间维护MyLibrary和SubLibrary之间的关系,这将是一个问题。除非你有其他理由想要在我不了解的MyLibrary中封装SubLibrary的实例,否则我将摆脱那个中间层,让你的Web服务只返回SubLibrary的一个实例。所以你只需要:

[WebMethod]
public SubLibrary GetInfo()
{

    return new Sublibrary();
}

在客户端应用中:

private void GetInfo_Click(object sender, System.EventArgs e)
{
  WS.WebService services = new WS.WebService();

  SubLibrary info = services.GetInfo();  // This of course doesn't convert.

  MessageBox.Show(info.GetValue());
}

通过Web服务传递复杂对象的好方法是:将一个实例的所有数据成员序列化为XML,通过网络发送,然后将其反序列化为另一端的实际数据。不要将它视为通过网络发送实际类(使用非数据成员)。

答案 2 :(得分:0)

通常,您需要为服务添加Web引用。这将创建一个客户端代理,其中包含客户端可用于调用Web服务而不是公共库的类。

在你的情况下,它可能看起来像:

WS.WebService services = new WS.WebService();

// Use client side proxy in same namespace as generated web reference
WS.MyLibrary info = services.GetInfo();


我似乎记得在生成的代理类中替换我的公共库(作为测试),一切似乎都有效。但不建议这样做,也不保证能够正常工作。

它可能只是您的示例,但您的MyLibrary类没有要返回的数据。原因是XmlSerializer(由运行时用于在XML和CLR对象之间进行转换)仅序列化对象的公共属性和字段。 MyLibrary和SubLibrary不公开任何属性或公共字段,因此不会序列化数据。有关详细信息,请参阅XML and SOAP Serialization