gpt4 book ai didi

c# - 表达式树序列化器

转载 作者:太空狗 更新时间:2023-10-29 23:24:07 29 4
gpt4 key购买 nike

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

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

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

这意味着我在 WCf 端有一个调用:

ImageDTO[] GetImages(XElement exp);

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

但我不确定该怎么做,而且我没有找到任何示例...

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

也许有人可以帮忙举个例子。

最佳答案

有一个 IQueryable<T> 的实现在框架中 - MSDN: EnumerableQuery<T>

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

您必须测试它以查看它是否适用于该表达式树序列化程序。

var iQueryable = new EnumerableQuery<Model>( Enumerable.Empty<Model>() );

var query = iQueryable.Include( ... ).Where( ... ).OrderBy( ... );

var expressionTree = query.Expression;

然后您可以序列化表达式,将其通过网络发送,然后反序列化。


那么问题是表达式树是基于一个EnumerableQuery<T> .

因此您需要将其替换为您的 IQueryable<T>来自你的真实DbContext

这有点困惑,但我已经使用 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 );

关于c# - 表达式树序列化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15887797/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com