We don't make this easy, which is by accident not design.
Internally, DevForce creates an EntityQuerySurrogate when sending a query to the server. This is essentially a wrapper over the query expression, along with some means of rehydrating the query. Unfortunately, this also has an internal constructor.
You can, though, do some of what the surrogate does yourself using the IdeaBlade.Linq.SerializedExpression class. You need to add this type as a known type on both client and server. You can create a SerializedExpression for a whole query, or a portion of it, as you want here. It's a bit tricky to use.
To build SerializedExpressions for your query parts you can do something like this:
var p1 = PredicateBuilder.Make<Product>(p => p.Discontinued == false);
var exp1 = SerializedExpression.ToSerializedExpression(p1);
var ss = new SortSelector(typeof(Product), "ProductName");
var exp2 = SerializedExpression.ToSerializedExpression(ss.ToLambdaExpression());
You'd then pass the SerializedExpressions to the server method, which could build a query as follows:
var p1 = args[0] as SerializedExpression; // where
var p2 = args[1] as SerializedExpression; // sort
var exp1 = p1.ToExpression() as Expression<Func<Product, bool>>;
var exp2 = p2.ToExpression() as Expression<Func<Product, string>>;
var query = em.GetQuery<Product>().Where(exp1).OrderBy(exp1);
As you can see, it's a bit messy rehydrating the expresions. If you don't know the entity type, you can pass that with the IdeaBlade.Core.TypeWrapper class, which is specifically designed for serializing type information.
You could instead build up the dynamic query on your client and pass the query expression to your server method. It would look something like this:
var p1 = PredicateBuilder.Make<Product>(p => p.Discontinued == false);
var ss = new SortSelector(typeof(Product), "ProductName");
var query = em.Products.Where(p1).OrderBySelector(ss);
var exp = SerializedExpression.ToSerializedExpression(query.Expression);
On the server you'd build up the query like this:
var p1 = args[0] as SerializedExpression; // query
var exp = p1.ToExpression();
var baseQuery = (IQueryable)TypeFns.ConstructGenericInstance(typeof(EntityQuery<>), typeof(Product));
var query = (EntityQuery)TypeFns.ConstructGenericInstance(typeof(EntityQuery<>),
new Type[] { baseQuery.ElementType }, exp, baseQuery);