c# - Expression Tree Serializer -
i want use linq expressions on client side, serialize them , execute them on server side.
for want use: http://expressiontree.codeplex.com/
but want execute them agains own wcf call.
that means have call on wcf side:
imagedto[] getimages(xelement exp);
i want have iqueryable on client side (on can execute linq expressions), , have iqueryable on serverside (from data acess layer, on wich want execute serialized expression).
but i'm not sure how this, , don't find examples...
on client side think should implement query in class, class tell in constructor use implementation of queryprovider (from call wcf service). i'm not sure if correct...
maybe can example.
there's implementation of iqueryable<t>
in framework - msdn: enumerablequery<t>
if can use on client build query, can whole expression tree iqueryable<t>.expression
property.
you'll have test see if works expression tree serializer.
var iqueryable = new enumerablequery<model>( enumerable.empty<model>() ); var query = iqueryable.include( ... ).where( ... ).orderby( ... ); var expressiontree = query.expression;
you can serialize expression, squirt accross wire , deserialize it.
then problem expression tree based on enumerablequery<t>
.
so need replace iqueryable<t>
source real dbcontext
this gets bit messy, i've written implementation using 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; }
and expressionvisitor
itself:
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 ); } }
calling straight forward:
type entitytype = ... expression expression = ... dbcontext db = ... objectcontext ctx = ( ( iobjectcontextadapter ) db ).objectcontext; iqueryable query = fixupexpressiontree( ctx, entitytype, expression );
Comments
Post a Comment