Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用WebServices返回自定义对象_C#_Web Services_.net 1.1 - Fatal编程技术网

C# 如何使用WebServices返回自定义对象

C# 如何使用WebServices返回自定义对象,c#,web-services,.net-1.1,C#,Web Services,.net 1.1,[问题] 创建了要部署在服务器机器和客户端机器上的共享库之后,如何在客户端服务器和库提供的类之间进行通信 通过web服务传输信息似乎不起作用,因为web服务返回的序列化对象是一个不会转换为共享库的web服务类 我是否错误地使用了Web服务?有更好的办法吗 [示例] public class MyLibrary { private SubLibrary sublib = new SubLibrary(); public class MyLibrary() { }

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

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

我是否错误地使用了Web服务?有更好的办法吗

[示例]

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

    public class MyLibrary()
    {
    }

    public string GetValue()
    {
        return sublib.GetValue();
    }
}
public class SubLibrary
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }
}
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());
}
MyLibrary.cs和SubLibrary.cs位于客户端应用程序要使用的共享程序集中

MyLibrary.cs

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

    public class MyLibrary()
    {
    }

    public string GetValue()
    {
        return sublib.GetValue();
    }
}
public class SubLibrary
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }
}
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());
}
SubLibrary.cs

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

    public class MyLibrary()
    {
    }

    public string GetValue()
    {
        return sublib.GetValue();
    }
}
public class SubLibrary
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }
}
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());
}
WebService.asmx.cs

[WebMethod]
public MyLibrary GetInfo()
{
    return new MyLibrary();
}
客户端应用程序

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

    public class MyLibrary()
    {
    }

    public string GetValue()
    {
        return sublib.GetValue();
    }
}
public class SubLibrary
{
    private string str = "Hello World";

    public SubLibrary()
    {
    }

    public string GetValue()
    {
        return str;
    }
}
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());
}

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

由于它是C#1.2,所以您既没有可用于翻译它们的分部类,也没有可用于欺骗的扩展方法

选项(我可以看到):

  • 编写一个静态实用方法,在两个对象模型之间费力地进行转换
  • 同上,但使用的是
    XmlSerializer
    (代码更少,但速度不够快)
  • 接受它
  • 升级到WCF(相当大的变化)

对于Web服务,通过网络发送的每个对象的类型都必须是可序列化的。通过实现IXmlSerializable接口,可以使子库可序列化

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,并且它包含子库的实例,因此在序列化期间必须维护MyLibrary和子库之间的关系,这将是一个问题。除非您有其他原因想将子库的实例封装到我不知道的MyLibrary中,否则我会去掉中间层,让您的Web服务只返回子库的实例。所以你只需要:

[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,通过网络发送,然后在另一端反序列化为真实数据。不要认为它是通过网络发送实际的类(包含非数据成员)

通常,您会向服务添加一个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不公开任何属性或公共字段,因此不会序列化任何数据。有关更多信息,请参见

使用
IXmlSerializable
会给web服务带来更多混乱,因为代理不会有代码……他说的是在网络的任何一端都使用相同的类,所以这不应该是个问题。如果OP是为公众消费设计web服务,我绝对同意你的观点。+1@Marc:感谢你的洞察力和其他选择。的确,这是1.1中的一大难题。@马克:如果你在.NET 3.5上,你将如何使用分部类或扩展方法来转换对象?对于分部类,你可以添加静态转换运算符(显式/隐式)。使用扩展方法,您可以添加
ConvertToFoo()
方法等。我理解这一点。我试着提出3点:典型的方法是什么(因为没有优雅的解决方案),我以前通过修改代理和删除生成的实体并为我的公共库添加一个using(但这不是一个好主意,IMO),并且示例代码没有公开任何属性(它使用未序列化的方法)。当然,我可能失败了。:)注意:我被告知要使用的实现与您所说的Tuzo相同,只是修改了生成的实体。就个人而言,我更喜欢Marc创建适配器的方法。最好用分层的方法来定位痛苦,而不是求助于手动编辑生成的代码。此外,我们还发现,必须对原始设计和代码中生成的实体进行手动编辑,以允许web服务序列化。这使得设计变得复杂,因为必须公开不需要公开的类和方法。