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(相当大的变化)
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服务序列化。这使得设计变得复杂,因为必须公开不需要公开的类和方法。