【问题标题】:How can I pass a lambda expression to a WCF service?如何将 lambda 表达式传递给 WCF 服务?
【发布时间】:2011-06-22 16:41:41
【问题描述】:

我当前的项目使用的是 IDesign 架构,所以我的所有层都是服务。我想让我的资源访问层的 CRUD 中的 Read 方法采用 lambda 表达式形式的谓词以及要提取的相关对象列表。这样资源访问层就非常通用了。

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

现在我发现了一些应该很明显的事情,那就是我无法序列化 lambda 表达式。我研究了将字符串解析为 lambda 表达式,但这也是不行的。

我可以使用任何方法将 lambda 表达式传递给服务吗?有没有更好的方法来做我想做的事情?

【问题讨论】:

  • 您真的希望您的 Web 服务接受任何形式、形状或颜色的可执行代码吗?我会考虑这种方法的安全方面。
  • 充其量你可以让它接受一个表达式的序列化版本,但不是一个 lambda,lambda 是一个方法指针,一个表达式是可以编译、分析等的东西的表示. 但是,我会再次考虑这里的安全方面。在我看来,这就是将 SQL 作为查询字符串的一部分传递给 Web 应用程序。
  • 这个服务不会暴露,它用在架构的更高层。而且我相信我读到过,表达式也不能被序列化,至少不是没有很大的困难。
  • Lambdas 不能被序列化,它们已经被编译为可执行代码,即。它们是指向可执行代码的方法指针。一个表情,至少你有一个战斗的机会,但也不容易。可能,不容易。使用 lambda,您将不得不反编译代码,并将 IL 传递给服务器,而这在这种情况下不一定有效。
  • @OpticalDelusion:关键问题是“不接触谁?”要回答安全问题,您需要做的是建立一个威胁模型。也就是说,绘制系统中所有不同组件的图表,然后确定这些组件之间的“信任边界”是什么。然后问自己“每个组件都保护了哪些资源?”以及“攻击者如何在每个边界破坏受保护的资源?”如果没有办法让危险系统被边界外的攻击者引诱攻击资源,那么你很好。

标签: c# .net wcf


【解决方案1】:

我们必须在 LINQ-to-Just-About-Everything 中解决这个问题。比如在做 LINQ-to-SQL 的时候:

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

不知何故,lambda c=&gt;c.City == "London" 和 c=&gt;c.Name 的内容需要以服务器可以理解的形式出现在 SQL 服务器上。显然,我们不能将 lambdas 持久化到服务器。

我们所做的是将 lambdas 转换为表达式树,在运行时分析表达式树,从中构建一个实际的 SQL 字符串,然后将该字符串发送到服务器进行处理。

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

如果您对这在 LINQ 中的工作方式感兴趣,LINQ-to-SQL 架构师 Matt Warren 撰写了一系列关于如何自己动手的博客文章:

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

【讨论】:

    【解决方案2】:

    也许动态查询适用于您的情况?

    http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

    您可以将 where 子句字符串传递给将验证并将其转换为表达式的服务

    【讨论】:

      【解决方案3】:

      WCF 不提供此功能。您基本上必须编写一个自定义序列化程序,该序列化程序接受 lambda 表达式并将表达式树转换为可序列化的数据。

      这就是 WCF 数据服务的工作方式。您在客户端代码中使用 lambda,它将这些 lambda 表达式分解为字符串,然后将查询字符串传递给数据服务,然后将字符串转换回 lambda,并将其应用于服务器端的 IQueryable。

      可行,但您必须为此编写大量自定义序列化代码。另外,让我们明确一点,这些将是 lamdba 表达式,而不是包含可以在服务器端执行的随机代码的完整 lambda 方法。

      【讨论】:

        【解决方案4】:

        我使用 CodePlex 上的 this 库来序列化/反序列化表达式树(但它的先前版本),它可以完成工作。

        这里还有一些其他类似的问题,比如这个: Serializing and Deserializing Expression Trees in C#

        【讨论】:

          【解决方案5】:

          创建一个Query Object 并将其传递给您的服务。

          看看这是否有帮助:

          http://ruijarimba.wordpress.com/2011/05/09/entity-framework-and-t4-generate-query-objects-on-the-fly-part-1/

          一个例子:

          var search = new AlbumSearch();
          search.PriceFrom = 5;
          search.PriceTo = 10;
          search.Artist = new ArtistSearch(){ Name = "Metallica" };
          search.Genre = new GenreSearch(){ NameContains = "Metal" };
          
          var albuns = from x in repository.All<Album>(search.GetExpression())
                            select x;
          

          【讨论】:

            【解决方案6】:

            我在codeplex中发现了一个项目开源是这个问题的解决方案

            表达式树序列化器

            项目描述 一个 .NET 4.0 和 Silverlight 4 类库,用于序列化和反序列化 Expression 实例。另外:Silverlight 的 WCF IQueryable LINQ 提供程序和 Web Http (REST) 客户端,它提供了比 WebClient 更易于使用的简化 REST 客户端 API(即 WCF 的 WebChannelFactory)。

            在这个链接上

            http://expressiontree.codeplex.com/

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多