表达式树序列化器

我想在客户端使用Linq表达式,序列化它们并在服务器端执行它们。

为此,我想使用: http : //expressiontree.codeplex.com/

但我想再次执行它们自己的WCF调用。

这意味着我在WCf方面有一个电话:

ImageDTO[] GetImages(XElement exp); 

我现在希望在客户端有一个IQueryable(我可以在其上执行Linq表达式),并且我在Serverside上有一个IQueryable(从我的数据访问层,我希望执行序列化表达式)。

但我不知道该怎么做,我没有找到任何例子……

在客户端我认为我应该在一个类中实现Query,这个类我在构造函数中告诉我使用我的QueryProvider实现(从我调用WCF服务的地方)。 但我不确定这是否正确……

也许有人可以帮助一个例子。

框架中有一个IQueryable的实现 – MSDN: EnumerableQuery

如果您可以在客户端上使用它来构建查询,则可以从IQueryable.Expression属性获取整个表达式树。

您必须对此进行测试以查看它是否适用于Expression Tree Serializer。

 var iQueryable = new EnumerableQuery( Enumerable.Empty() ); var query = iQueryable.Include( ... ).Where( ... ).OrderBy( ... ); var expressionTree = query.Expression; 

然后,您可以序列化表达式,将其喷射到电线上,然后对其进行反序列化。


然后问题是表达式树基于EnumerableQuery

因此,您需要将其替换为真实DbContext IQueryable

有点乱,但我使用ExpressionVisitor:编写了一个实现ExpressionVisitor:

 IQueryable FixupExpressionTree( ObjectContext ctx, Type entityType, Expression expression ) { var tObjectContext = ctx.GetType(); var mCreateObjectSetOpen = tObjectContext.GetMethod( "CreateObjectSet", new Type[ 0 ] ); var mCreateObjectSetClosed = mCreateObjectSetOpen.MakeGenericMethod( entityType ); var objectQuery = ( ObjectQuery ) mCreateObjectSetClosed.Invoke( ctx, null ); var eFixed = new Visitor( objectQuery, entityType ).Visit( expression ); var qFixed = ( ( IQueryable ) objectQuery ).Provider.CreateQuery( eFixed ); return qFixed; } 

ExpressionVisitor本身:

 public class Visitor : ExpressionVisitor { ObjectQuery _Source = null; Type _EntityType = null; public Visitor( ObjectQuery source, Type entityType ) { _Source = source; _EntityType = entityType; } protected override Expression VisitConstant( ConstantExpression node ) { if ( !node.Type.Name.Contains( "EnumerableQuery" ) ) return base.VisitConstant( node ); var eConstantInstance = Expression.Constant( _Source ); var eConstantArgument = Expression.Constant( MergeOption.AppendOnly ); var tObjectQueryOpen = typeof( ObjectQuery<> ); var tObjectQueryClosed = tObjectQueryOpen.MakeGenericType( _EntityType ); var eMergeAsMethod = tObjectQueryClosed.GetMethod( "MergeAs", BindingFlags.Instance | BindingFlags.NonPublic ); return Expression.Call( eConstantInstance, eMergeAsMethod, eConstantArgument ); } } 

称之为直截了当:

 Type entityType = ... Expression expression = ... DbContext db = ... ObjectContext ctx = ( ( IObjectContextAdapter ) db ).ObjectContext; IQueryable query = FixupExpressionTree( ctx, entityType, expression ); 

为了解决我的问题,我使用了Interlinq,但是我分叉了一个版本,因此它也适用于Silverlight。

https://github.com/jogibear9988/Interlinq-2