如何将Lambda表达式传递给WCF服务?

16

我的当前项目正在使用IDesign架构,因此我的所有层都是服务。我希望在资源访问层的CRUD中,我的Read方法可以接受一个lambda表达式形式的谓词以及一些相关对象的列表作为参数。这样资源访问层将会非常通用。

[OperationContract]
Result<MyObject> ReadObjects(Func<MyObject, bool> predicate, string[] includes);

现在我发现了一件应该很明显的事情,那就是我无法序列化lambda表达式。我尝试将一个字符串解析成lambda表达式,但是不行。

有没有什么方法可以用来传递lambda表达式到一个服务中呢?或者有没有更好的方式来实现我想要做的事情呢?


15
你是否真的希望你的网络服务接受任何形式、形状或颜色的可执行代码?我会考虑这种方法的安全性方面。 - Lasse V. Karlsen
2
最好的情况可能是你可以让它接受一个表达式的序列化版本,但不能是Lambda,Lambda是指向方法的指针,而表达式则是对可以编译、分析等某些东西的表示。但我认为在这里要考虑安全方面的问题。在我看来,这与将SQL作为查询字符串的一部分传递给Web应用程序一样危险。 - Lasse V. Karlsen
此服务不会被暴露,它在架构的更高层使用。而且我相信表达式也无法被序列化,至少不是没有重大困难的情况下。 - Alec
2
Lambda表达式无法被序列化,它们已经编译为可执行代码,即它们是指向可执行代码的方法指针。至少使用表达式还有一定的机会,但即使使用表达式也并不容易。虽然可能,但并不容易。对于Lambda表达式,您需要反编译代码,并将IL传递到服务器,但在该上下文中这并不一定有效。 - Lasse V. Karlsen
1
@OpticalDelusion:关键问题是“不暴露给谁?”为了回答安全问题,您需要建立一个威胁模型。也就是说,绘制系统中的所有不同组件的图表,然后确定这些组件之间的“信任边界”。然后问自己“每个组件保护哪些资源?”以及“攻击者如何在每个边界上破坏受保护的资源?”如果没有危险系统被引诱攻击边界外的资源的方法,那么您就很好了。 - Eric Lippert
显示剩余4条评论
6个回答

25

我们必须在LINQ-to-Just-About-Everything中解决这个问题。例如,在进行LINQ-to-SQL时:

var results = from c in customers where c.City == "London" select c.Name;

一些lambda表达式的内容,例如c=>c.City == "London"c=>c.Name需要以服务器可理解的形式出现在SQL服务器上。显然,我们不能将lambda表达式持久化到服务器中。

相反,我们将lambda表达式转换为表达式树,在运行时分析表达式树,构建实际的SQL字符串,并将该字符串发送到服务器进行处理。

您也可以做同样的事情。为您的服务器创建查询语言。在客户端,将lambda表达式转换为表达式树。在运行时分析它们,将结果转换为您的查询语言中的字符串,然后将查询发送到服务。

如果您对LINQ中的工作原理感兴趣,LINQ-to-SQL架构师Matt Warren已经撰写了一系列关于如何自己完成此操作的博客文章:

http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx


6

4
WCF并没有内置此功能。您需要编写自定义序列化器,将lambda表达式转换为可序列化的数据。
WCF DataServices使用的就是这种方式。您可以在客户端代码中使用lambda表达式,它会将这些lambda表达式分解为字符串,并将其传递到数据服务的查询字符串中,然后将字符串转换回lambda表达式,并应用于服务器端的IQueryable。
虽然可行,但您需要编写大量自定义序列化代码。同时,让我们明确一点,这些将是lambda表达式,而不是包含可能在服务器端执行的任意代码的完整lambda方法。

0

我在 CodePlex 上找到了一个开源项目,它是解决这个问题的解决方案。

表达式树序列化器

项目描述:这是一个 .NET 4.0 和 Silverlight 4 类库,用于序列化和反序列化表达式实例。此外还包括:WCF IQueryable LINQ 提供程序和 Web Http(REST)客户端,为 Silverlight 提供了一个简化的 REST 客户端 API(即 WCF 的 WebChannelFactory),比 WebClient 更易于使用。

链接如下:

http://expressiontree.codeplex.com/


0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接