.net 如何使用WCF';实现客户端异步调用;渠道工厂<;T>;?

.net 如何使用WCF';实现客户端异步调用;渠道工厂<;T>;?,.net,web-services,wcf,asynchronous,.net,Web Services,Wcf,Asynchronous,假设我们正在使用WCF的ChannelFactory为计算器web服务编写客户端。服务契约通过实现服务和客户端引用的第三个程序集共享。以下是服务合同(不能更改!) ChannelFactory创建一个透明代理对象,该对象“模拟”ICalculator服务契约,将方法调用传递给RealProxy对象,然后RealProxy对象将消息发送到WCF通道堆栈。是否有一种方法可以操纵WCF(仅在客户端!)来自动公开任务友好型服务操作,类似于VS自动生成的服务代理 要明确的是,无论如何,我都不想将我的服务修

假设我们正在使用WCF的ChannelFactory为计算器web服务编写客户端。服务契约通过实现服务和客户端引用的第三个程序集共享。以下是服务合同(不能更改!)

ChannelFactory创建一个透明代理对象,该对象“模拟”ICalculator服务契约,将方法调用传递给RealProxy对象,然后RealProxy对象将消息发送到WCF通道堆栈。是否有一种方法可以操纵WCF(仅在客户端!)来自动公开任务友好型服务操作,类似于VS自动生成的服务代理

要明确的是,无论如何,我都不想将我的服务修改为异步友好的。我希望我的客户端在等待正常阻塞服务调用完成时继续处理。

公共接口ICalculator
public interface ICalculator 
{
    Task<int> Add(int x, int y);
}
{ 任务添加(整数x,整数y); }
用这个作为合同。但是,您需要确保运行的是.NET4.5,这样才能正常工作

记住在服务器端使用此模式

public class Calculator : ICalulator
{
    public Task<int> Add(int x, int y)
    {
        int result = x + y;
        return Task.FromResult(result);
    }
}
公共类计算器:ICalulator
{
公共任务添加(整数x,整数y)
{
int结果=x+y;
返回Task.FromResult(结果);
}
}

我使用ILSpy进行了一些探索,发现ChannelFactory和VS的服务代理代码都在封面下利用相同的代码为ICalculator生成透明代理。唯一的区别是,auto gen代码创建了一个自定义接口,该接口镜像了服务的约定以及任务异步方法,OperationContract属性指向“真正的”服务操作URI

[ServiceContract]
public interface ICalculatorClient
{
    [ServiceOperation(Action="http://tempuri.org/ICalculator/Add")]
    Task<int> AddAsync(int x, int y);
}
[服务合同]
公共接口iCalculator客户端
{
[ServiceOperation(操作=”http://tempuri.org/ICalculator/Add")]
任务AddAsync(intx,inty);
}
因此,我没有使用包含原始服务的服务契约的程序集,而是在客户机代码中创建了我自己的iCalculator客户机服务契约(名称只是为了消除此测试的歧义),其中包含所需的任务异步方法调用,仅具有必需的ServiceOperation属性,且Action属性指向服务器契约上“真实”服务操作的URI


在运行时,观察到了期望的行为:我的客户机代码在等待服务器的响应时继续运行,最终收到了预期的响应。这项服务并不明智,因为它没有被修改以满足客户的需求。客户更聪明,可以控制与web服务交互的细节。

请重新阅读我的帖子,我在帖子中提到我不能更改合同,也不想更改合同。我不想在不必要的时候暴露任务。我应该能够等待任何服务操作,无论其方法签名如何,因为它是一个I/O操作,非常类似于流。要证明客户端可以始终等待任何服务调用,请参阅VS的auto-gen服务代理实现。我基本上希望这样,但是使用ChannelFactory。您需要在客户端“公开”任务,因为您需要在调用时使用async,以确保无线程异步(否则您只能获得并发异步)。我演示了如何在服务器端实现同步调用。如果您希望在不更改服务合同的情况下实现这一点,我建议您使用服务引用来创建接口,以减少手动步骤。请参阅我对您对该问题/线程的“答案”的类似评论的评论回复,因为它也适用于你在这里的最新评论。简言之,你失去了使用共享合约程序集而不是使用添加服务引用的所有优势。我不同意。服务参考有很多缺点。有其他方法可以重新获得自动生成代码的便利性,如T4模板,而不受代理的限制:请参阅此MSDN文章:T4与cs文件中的接口不兼容(请尝试获取CodeDom以了解部分),只是由于dll反射而中断(dll读取锁定会停止编译)。和Roslyn一起使用T4,可能有用,但我从未使用过。我从未建议你使用代理。我更喜欢渠道工厂。我只是建议你在合同上加上服务参考。很有趣的建议,阿隆。我从未想过运行代码生成器只是为了提取接口,然后使用ChannelFactory。对于一个共同的实践来说,这可能是两全其美的。如果你编辑你的答案来反映这一点,我会非常乐意给你一个“答案”的分数。
[ServiceContract]
public interface ICalculatorClient
{
    [ServiceOperation(Action="http://tempuri.org/ICalculator/Add")]
    Task<int> AddAsync(int x, int y);
}