WCF ChannelFactory与生成代理


82

只是想知道在什么情况下仅使用ChannelFactory调用调用时,您希望从WCF服务生成代理?

这样,您将不必生成代理,也不必担心在服务器更新时重新生成代理吗?

谢谢


始终使用ChannelFactory。我不能足够强烈地说明这一点。
汤姆·雷德芬

Answers:


88

创建WCF客户端的基本方法有3种:

  1. 让Visual Studio生成您的代理。通过读取WSDL,此自动生成连接到服务的代码。如果服务由于任何原因发生变化,则必须重新生成它。这样做的最大好处是易于设置-VS具有向导,并且完全是自动的。缺点是您依靠VS为您完成所有艰苦的工作,因此您会失去控制。

  2. 使用ChannelFactory具有已知的接口。这取决于您具有描述服务(服务合同)的本地接口。最大的优点是可以更轻松地管理更改-您仍然必须重新编译和修复更改,但是现在您不是在重新生成代码,而是在引用新接口。通常,当您同时控制服务器和客户端时,会使用此方法,因为可以更轻松地对两者进行单元测试。但是,可以为任何服务(甚至是REST服务)编写接口-请查看此Twitter API

  3. 编写自己的代理-使用HttpClient或,这很容易做到,特别是对于REST服务WebClient。这为您提供了最精细的控制,但是以字符串中的大量服务API为代价。例如:var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;-如果API的详细信息发生变化,则直到运行时您都不会遇到错误。

就我个人而言,我从来不喜欢选项1-依靠自动生成的代码是混乱的,并且失去了太多控制权。再加上它经常会引起序列化问题-我最终得到了两个相同的类(服务器代码中的一个,一个自动生成的),这些类可以被束缚起来,但是很痛苦。

选项2应该是完美的,但是Channels有点过于局限-例如,它们完全丢失了HTTP错误的内容。也就是说,拥有描述服务的接口更容易编写和维护。


4
@MurHaf Nope-这个答案完全是我自己的工作。我总是归功于他人的贡献。我根据多年来在.Net中使用SOAP服务从事各种工作的经验编写了此答案。您链接到的那篇文章是从2013年3月开始的,而我的答案是在3年之前的2010年4月写的!如果发生窃,他会抄袭我。您应该在提出指控之前先检查日期,因为这样做很容易。
基思(Keith)

@MurHaf我们甚至无法得出相同的结论-该文章建议自动生成“简单”代理(选项1)。我将其描述为易于设置,但混乱且难以维护。他甚至没有讨论编写您自己的代理(选项3)。
基思(Keith)

1
我认为还应该提到SvcUtil,因为这是“编写”客户端的最常用方法之一。
2014年

21

我将ChannelFactory与MetadataResolver.Resolve方法一起使用。客户端配置很麻烦,因此我从服务器获取了ServiceEndpoint。

使用ChannelFactory(Of T)时,T是可以从项目中的引用获取的原始合同,也可以是生成的合同实例。在某些项目中,由于无法添加对合同dll的引用,因此从“服务引用”生成了代码。您甚至可以生成带有服务引用的异步合同,并将该合同接口与ChannelFactory一起使用。

对我而言,使用ChannelFactory的要点是摆脱WCF客户端配置信息。在下面的示例代码中,您可以看到如何在没有配置的情况下实现WCF客户端。

Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()

在我的最后一个项目中,检查availableBindings是否使用net.tcp或net.pipe(如果可用)。这样,我便可以根据需要使用最佳的可用绑定。我仅依赖于服务器上存在元数据终结点的事实。

我希望这有帮助

顺便说一句,这是使用.NET 3.5完成的。但是,它也适用于4.0。


很棒的东西。我也对配置使用MetadataResolver.Resolve,但是我没有考虑从服务器解析绑定。很好点!
史密斯卧铺

提及提及The main point of using ChannelFactory to get rid of the WCF client config
Kurubaran '16

11

为了使用它,ChannelFactory<T>您必须愿意在服务和客户端之间共享合同程序集。如果可以的话,ChannelFactory<T>可以为您节省一些时间。


@Charles-您能解释为什么这不是真的吗?
阿兰·穆赫兰

6
@亚兰:我认为安德鲁的意思是正确的-如果您不想生成合同类的传真,那么您将需要访问原始文件。的确,您需要一种或另一种方式拥有这些合同类。您可以生成它们,手工编写它们,或获取服务源代码(如果使用相同的语言)。共享程序集是最简单的方法,但这并不总是可行的。(也许我只是从字面上理解安德鲁,但这里的重要性很重要。)
Igby Largeman 2011年

2
@Charles好的,所以您说的是即使您无法通过手工编码T的接口然后使用它来访问程序集,也可以使用ChannelFactory <T>。
阿兰·穆赫兰

1
@Aran:是的,可以通过手工编码或使用诸如svcutil之类的工具(假设该服务正在运行并且可以访问)。
Igby Largeman 2011年

9

代理将建立异步函数,这对于它来说是一个不错的选择。


2
是的-同时,Visual Studio的“添加服务引用”以及命令行上的svcutil.exe都使您的配置无法识别....至少使用svcutil.exe,您可以定义“ / noconfig”开关.....
marc_s

1
ChannelFactory还提供了异步方法:msdn.microsoft.com/zh-cn/library/ms731177.aspx但是我更喜欢使用T4模板使用ThreadPool创建异步类,该类将调用同步方法。
SandRock 2011年

1
作为更新:使用.NET 4.5,ChannelFactory <T>也支持基于任务的异步功能。
gimpf

8

我的回答是对KeithAndrew Hare的回答的一种总结。

如果您不控制服务器,而只有WSDL / URL,则使用Visual Studio或svcutil生成代理。(请注意,当svcutil更好地工作时,Visual Studio有时会失败)。

当您同时控制服务器和客户端时,共享接口/合同并调用ChannelFactory


2

这不仅仅是节省时间的问题。使用WSDL生成的代理很危险,因为如果您忘记更新服务引用,则可能会使解决方案处于不一致状态。一切都可以编译,但是服务合同已被破坏。我明确建议尽可能使用ChannelFactory,这样会使您的生活更加轻松。

一种可能的替代方法是编写一个每次构建项目时都调用SVCUtil实用程序以创建代理的预构建脚本,但是无论如何ChannelFactory都更加简洁明了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.