繁体   English   中英

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

[英]How can I pass a lambda expression to a WCF service?

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

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

现在,我发现了一些本应显而易见的东西,那就是我无法序列化lambda表达式。 我研究过将字符串解析为lambda表达式,但这也是不可行的。

有什么方法可以将lambda表达式传递给服务? 有没有更好的方法来做我想做的事情?

我们必须在LINQ to About 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 Server上。 显然,我们无法将lambda持久保存到服务器。

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

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

如果您对LINQ的工作方式感兴趣,则LINQ-to-SQL架构师Matt Warren撰写了许多博客文章,介绍如何自己做:

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

也许在您的情况下可以进行动态查询?

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

您需要将where子句字符串传递给服务,该服务将对其进行验证并将其转换为表达式

WCF没有开箱即用的功能。 从本质上讲,您必须编写一个自定义序列化程序,该序列化程序使用lambda表达式并将表达式树转换为可序列化的数据。

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

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

我发现Codeplex中的项目开源是此问题的解决方案

表达式树序列化器

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

在此链接上

http://expressiontree.codeplex.com/

我在CodePlex上使用库对表达式树进行序列化/反序列化(但使用其以前的版本),并且可以正常工作。

这里还有其他类似的问题,例如: C#中的表达式树的序列化和反序列化

创建一个查询对象并将其传递给您的服务。

看看这是否有帮助:

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM