我应该直接绑定到从Web服务返回的对象吗?
我应该直接绑定到从Web服务返回的对象,还是应该将客户端对象绑定到我的gridcontrols?例如,如果我有一个返回对象Car的服务,是否应该有一个我用webservice Car对象中的值填充的客户端Car对象?
什么是最佳做法?
在Cdo中,我需要将类标记为可序列化,或者对它们进行特殊处理?
解决方案
这实际上取决于我们从Web服务获得的收益。如果它们是简单的数据传输对象,而我们仅显示数据,那么可以绑定。如果我们计划编辑对象,则可能没有用,因为我们需要跟踪更改。
我们在客户端上的对象和/或者集合是否跟踪更改?如果是这样,我们可以使用它们。
如果没有更改跟踪,那么我们将需要自己跟踪更改,因此我们可能需要平移对象或者将它们包装在某种东西中以跟踪更改。
同样,这实际上取决于我们所获得的东西,他们的支持,与他们一起做的事情以及服务器要更改返回的响应。
我们可以做的一件事是使用所需的任何其他功能创建与Web Service数据协定相对应的客户端类,并将Web Service引用设置为重用现有类型。这样就没有理由创建要绑定的其他包装器类。
如果直接绑定到Web服务类型,则将引入耦合。如果将来Web服务发生更改,则可能会产生不希望有的副作用,这意味着需要更改许多代码。
例如,如果我们今天正在使用.asmx Web服务,然后明天再使用WCF,该怎么办?如果我们使用了WCF不会序列化的类型,那可能意味着对代码进行了大量更改。
从长远来看,通常最好先创建特定的客户端对象,然后再与Web服务数据协定类型进行相互转换。看起来可能需要做很多工作,但是当我们需要重构时,由于所做的更改都集中在一个地方,因此通常可以得到很大的回报。
这是一个很好的问题,与我自问的两个问题相同:
- 大型复杂对象作为Web服务的结果。
- ASP.NET Web服务结果,代理类和类型转换。
这两个对我们来说都是值得阅读的。
这是我的两点:
- 尽可能使Web服务的返回类型保持为原语。这不仅有助于减小消息的大小,而且还可以降低接收端的复杂性。
- 如果确实需要返回复杂的对象,则将它们作为原始xml字符串返回(我将在下面说明)。
然后,我要做的是创建一个单独的类,该类代表对象并处理它的xml。我确保可以轻松地从该类实例化该类并将其序列化为xml。然后,两个项目(Web服务和客户端)都可以引用包含具体对象的DLL,但没有与代理类的烦人耦合。如果我们共享代码,则这种耦合会导致问题。
例如(使用Car
类):
- Web Service(
CarFactory
)方法BuyCar(string make,string model)
是一种返回汽车的工厂方法。 - 我们还编写了一个对"汽车"对象进行修复的"机械"类,该类是在不了解Web服务的情况下开发的。
- 然后,为应用程序设置一个
Garage
类。我们可以向" CarFactory"服务添加网络引用以获取汽车,然后向车库添加一些" Mechanic",然后打开指关节,并准备从工厂购买一些汽车以使它们继续工作。 - 然后,当我们得到
CarFactory.BuyCar(" Audi"," R8")
的结果,然后告诉Mechanic.Inspect(myAudi)
时,编译器会抱怨,因为这一切实际上都是Car
类型为" CarFactory.Car",而不是原始的"汽车"类型,是吗?
因此,使用我建议的方法:
- 在自己的DLL中创建
Car
类。添加方法以实例化它并分别从XML到XML进行序列化。 - 创建
CarFactory
Web服务,添加对DLL的引用,像以前一样构建汽车,但是返回XML而不是返回对象。 - 创建
Garage
,并添加对Mechanic
,Car
DLL和CarFactory
Web服务的引用。调用" BuyCar"方法,现在它返回一个字符串,然后将该字符串传递给" Car"类,后者将重建其对象模型。机械的也可以在这些汽车上愉快地工作,因为一切都在同一个赞美诗表(或者DLL?)中歌唱:) - 一个主要的好处是,如果对象的设计发生变化,我们要做的就是更新DLL,并且Web服务和客户端应用程序将与流程完全分离。
注意:通常,创建两个与Web服务一起使用的Facade层并从XML结果自动生成对象通常是有用的。
我希望这是有道理的,如果没有的话,请大声疾呼,我会澄清一下。
如果我们同时是Web服务和客户端的所有者。
而且,我们需要将Web服务调用的参数设置为复杂的类,这些类不仅包含数据,而且还包含行为(实际编码的逻辑),然后在使用Web Service框架开发这些Web Service时会有些烦恼。
正如Rob Cooper的答案所建议的那样,我们可以将纯xml用作Web服务参数和xml序列化,但是有一个更干净的解决方案。
如果我们使用的是Visual Studio 2005(可能适用于2008),则可以按照本文中的说明自定义VS创建代理的方式:
在Visual Studio 2005中自定义生成的Web服务代理
这样,我们可以告诉VS使用我们自己的类,而不是生成代理类。
好吧,当我想到它时,它几乎与Rob Cooper提出的解决方案几乎相同,只是稍稍有些曲折,我们将不会自己编写Facade层,而是将VS本身用作该层。