Alec
Alec

Reputation: 1706

How can I pass a lambda expression to a WCF service?

My current project is using the IDesign architecture, so all of my layers are services. I wanted to have my Read method in the CRUD of my resource access layer take a predicate in the form of a lambda expression as well as a list of related objects to pull. This way the resource access layer will be very generic.

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

Now I have come to discover something that should have been obvious, and that is that I cannot serialize lambda expressions. I looked into parsing a string into a lambda expression, but that is a no go as well.

Is there any method that I can use to pass a lambda expression to a service? Is there a better way to do what I am trying to do?

Upvotes: 16

Views: 12221

Answers (6)

Hicham
Hicham

Reputation: 129

I found a project open source in codeplex is solution of this problem as subject

Expression Tree Serializer

Project Description a .NET 4.0 and Silverlight 4 class library that serializes and deserializes Expression instances. Also: a WCF IQueryable LINQ Provider and Web Http (REST) client for Silverlight that provides a simplified REST client API (i.e. WCF's WebChannelFactory) that's easier to use than WebClient.

on this link

http://expressiontree.codeplex.com/

Upvotes: 0

Rui Jarimba
Rui Jarimba

Reputation: 17979

Create a Query Object and pass it to your services.

See if this helps:

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

An example:

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;

Upvotes: 0

Kamarey
Kamarey

Reputation: 11079

I use this library on CodePlex to serialize/deserialize Expression trees (but its previous version), and it does the work.

There are also some other similar questions here like this one: Serializing and Deserializing Expression Trees in C#

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 660004

We have to solve this problem in LINQ-to-Just-About-Everything. For example, when doing LINQ-to-SQL:

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

somehow the content of the lambdas c=>c.City == "London" and c=>c.Name need to end up on the SQL server in a form the server understands. Clearly we cannot persist the lambdas to the server.

Instead what we do is turn the lambdas into Expression Trees, analyze the expression trees at runtime, build an actual string of SQL out of it, and send that string to the server for processing.

You can do the same thing. Create a query language for your server. On the client side, turn the lambdas into expression trees. Analyze them at runtime, turn the result into a string in your query language, and then send the query to the service.

If you're interested in how this works in LINQ, the LINQ-to-SQL architect Matt Warren has written a long series of blog articles on how to do it yourself:

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

Upvotes: 25

Drew Marsh
Drew Marsh

Reputation: 33379

WCF doesn't offer this out of the box. You would essentially have to write a custom serializer that took lambda expressions and turned the expression tree into a serializable piece of data.

This is how WCF DataServices works. You use lambdas in your client code, it decomposes those lambda expressions into strings which it passes on the querystring to the data service which then turns the string back into a lambda which it applies to a IQueryable on the server side.

Doable, but you will have to to write a lot of custom serialization code for this. Also, let's be clear, these would be lamdba expressions, not full lambda methods containing random code that could ever be executed on the server side.

Upvotes: 4

Jason Miesionczek
Jason Miesionczek

Reputation: 14448

Perhaps a dynamic query would work in your situation?

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

You would pass a where clause string to the service which would validate and convert it to an expression

Upvotes: 6

Related Questions