【问题标题】:Serializing Delegates in WCF Using a Surrogate?使用代理在 WCF 中序列化委托?
【发布时间】:2010-06-27 19:56:24
【问题描述】:

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

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

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

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

这是有目的的(简化的)序列:

  1. A 调用 B-pr​​oxy.Foo(callback)
  2. 回调通过 DelegateSurrogate 序列化。
  3. DelegateSurrogate 将委托存储在专用委托存储中并用令牌替换它
  4. 消息到达 B 的端点
  5. 令牌通过 DelegateSurrogate 反序列化
  6. DelegateSurrogate 构造一个生成的委托
  7. B.Foo(generatedCallback) 被调用
  8. 后来,B 调用了 generatedCallback(args)
  9. generatedCallback(args) 调用 A 端点上的专用通用合约:CallbackContract-proxy.GenericCallback(args)
  10. CallbackContract.GenericCallback(args) 在 A 的端点上调用
  11. 从存储中检索原始回调并调用:callback(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);
}

【问题讨论】:

  • 为什么标准的回调机制“繁琐”?
  • 因为您需要样板代码才能使用它,并且您需要学习这种机制。另外 - 我不相信它会在像 MSMQ 这样的单向渠道中工作。委托作为回调更直观,因为它们看起来像常规的 C# 代码。

标签: wcf delegates datacontract


【解决方案1】:

实际上,在这种情况下,我会研究Expression API。与委托不同,Expression 可以在运行时解构。 默认情况下你不能序列化它们,但是lot of work 已经在那个空间里完成了。这也有点像很多 LINQ 提供程序在后台执行的操作,例如 WCF 数据服务。

当然,另一种方法是简单地使用 lambda 表达式作为 RPC 的钩子,这就是我所描述的 here。实现这一点的代码可在 protobuf-net 树中免费获得。您可以通过使用属性将您的令牌与方法相关联来自定义它,并从MethodInfo 获取属性。

IMO,delegates 的问题在于它们与实现的耦合过于紧密,因此您不能在每一端都有不同的实现(这是一个常见的要求)。

表达式的优势在于 lambdas 仍然支持智能感知等,因此您可以执行以下操作:

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

并从中分别获得FooMethodInfo)、123和“abc”,包括捕获的变量、ref/out等。一切正常。

【讨论】:

  • 感谢您的回答,但这不是我想要的。首先,对于带有语句体的 lambda,表达式树不是一个选项。其次,我仍然不知道如何编写我的代理并将其连接到 WCF。我将在主帖中添加一个示例用例以尝试使其更清晰。
  • @Omer - 在 4.0 中,Expression 支持语句体。 C# 编译器 支持它,但Expression 支持。可以做到的。
  • 如果编译器不支持也没用。查看我的示例用法,看看我要做什么。我仍然认为没有必要序列化委托和/或表达式。我们只需要一个临时令牌,并将委托存储在客户端,直到服务器端调用“代理委托”。
  • @Omer - 你给出的例子在 C# 中工作得很好 - 网络上的东西不是语句体。如果你不想那样做:好的。但我知道这会奏效。
  • 是的,该示例没有使用语句体,因为我想简洁地表达我的要求。但我现在改了。
猜你喜欢
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多