在WCF中使用代理序列化委托?

在WCF中使用代理序列化委托?,wcf,delegates,datacontract,Wcf,Delegates,Datacontract,我有一个想法,但我需要帮助实现它 WCF在其合同中不支持委托。 相反,它有一个麻烦的回调契约机制,我正在寻找一种方法来克服这个限制 我考虑使用一个IDataContractSurrogate将契约中的每个委托替换为一个令牌,该令牌将被序列化到远程端点。在那里,令牌将反序列化为生成的委托。此生成的委托将发送一条通用回调消息,该消息封装了所有参数(调用委托时使用的参数) 通用回调消息将到达第一个端点,并在那里使用参数调用原始委托 以下是目的(简化)顺序: A调用B-proxy.Foo(回调) 回调通

我有一个想法,但我需要帮助实现它

WCF在其合同中不支持委托。 相反,它有一个麻烦的回调契约机制,我正在寻找一种方法来克服这个限制

我考虑使用一个
IDataContractSurrogate
将契约中的每个委托替换为一个令牌,该令牌将被序列化到远程端点。在那里,令牌将反序列化为生成的委托。此生成的委托将发送一条通用回调消息,该消息封装了所有参数(调用委托时使用的参数)

通用回调消息将到达第一个端点,并在那里使用参数调用原始委托

以下是目的(简化)顺序:

  • A调用B-proxy.Foo(回调)
  • 回调通过DelegateSubrogate序列化
  • DelegateSubrogate将代理存储在专用的代理存储中,并用令牌替换它
  • 消息到达B的端点
  • 令牌通过DelegateSubrogate反序列化
  • DelegateSubrogate构造生成的委托
  • 调用B.Foo(generatedCallback)
  • 稍后,B将调用generatedCallback(args)
  • generatedCallback(args)调用a端点上的专用通用约定:CallbackContract proxy.GenericCallback(args)
  • 在A的端点上调用CallbackContract.GenericCallback(args)
  • 从存储器中检索并调用原始回调:回调(args)
  • 我以前已经使用服务总线(
    NServiceBus
    )实现了这一点,但我想将这一想法应用到WCF中,这让我很为难。我知道如何实施步骤3、6、9和11。我还不知道如何连接WCF中的所有内容,尤其是代理部分

    就是这样——我希望我的问题有意义,这里的集体智慧将能够帮助我建立这一点

    以下是我所需解决方案的示例用法:

    // client side
    remoteSvc.GetEmployeeById(17, emp => 
    {
        employees.Add(emp);
        logger.log("Result received");
    });
    
    // server side
    public void GetEmployeeById(int id, Action<Employee> callback)
    {
        var emp = getEmpFromDb(id);
        callback(emp);
    }
    
    //客户端
    remoteSvc.GetEmployeeById(17,emp=>
    {
    添加(emp);
    logger.log(“收到结果”);
    });
    //服务器端
    public void GetEmployeeById(int-id,操作回调)
    {
    var emp=getEmpFromDb(id);
    回调(emp);
    }
    
    实际上,在这个场景中,我将研究
    表达式
    API。与委托不同,
    表达式可以在运行时解构。默认情况下,您无法序列化它们,但已在该空间中完成了一次序列化。这也有点像许多LINQ提供者在后台所做的,例如WCF数据服务

    当然,另一种方法是简单地使用lambda表达式作为RPC的钩子,这就是我所描述的。实现这一点的代码在protobuf网络树中免费提供。您可以使用一个属性将您的令牌与方法关联,并从
    MethodInfo
    中获取该属性,从而对此进行自定义

    在我看来,委托的问题在于,它们与实现的耦合太紧密,因此不能在每一端都有不同的实现(这是一个常见的需求)

    表达式的优点是lambdas仍然支持intellisense等,因此您可以执行以下操作:

    client.Invoke(svc => svc.Foo(123, "abc"));
    

    从中分别获得
    Foo
    (the
    MethodInfo
    )、123和“abc”,包括捕获的变量、
    ref
    /
    out
    ,等等。这一切都是有效的。

    为什么标准回调机制“麻烦”?因为您需要样板代码来使用它,您需要学习这种机制。另外,我不相信它会在像MSMQ这样的单向渠道中起作用。作为回调的代理更直观,因为它们看起来像普通的C#代码。谢谢你的回答,但这不是我想要的。首先,表达式树不是具有语句体的lambda的选项。其次,我仍然不知道如何编写我的代理并将其连接到WCF。我将在主帖中添加一个示例用例,以使其更加清晰。@Omer-在4.0中,
    Expression
    支持语句体。C#编译器不支持它,但
    表达式支持它。这是可以做到的。如果编译器不支持它,那就没用了。看看我的示例用法,看看我在追求什么。我仍然认为没有必要序列化委托和/或表达式。我们所需要的只是一个特殊的令牌,并将委托存储在客户端,直到服务器端调用“代理委托”。@Omer-您给出的示例在C#中很好用-连接上的东西不是语句体。如果你不想那样做:好的。但是我知道这是可行的。是的,这个例子没有使用语句体,因为我希望我的需求简洁明了。但我现在改了。