Some useful observation from Expressions world.
Let's imagine we have the following class:
And we use it in some IQueryable request in a following manner:
var queryable = new[] { new Foo {Items = new[] { 1, 2, 3 }} }.AsQueryable();
Note, that Items implements IEnumerable only, so this query is represented as:
Let's imagine we have the following class:
public class Foo { public int[] Items { get; set; } }
And we use it in some IQueryable request in a following manner:
var queryable = new[] { new Foo {Items = new[] { 1, 2, 3 }} }.AsQueryable();
var q = queryable.Select(x => x.Items.Select(y => y % 2 == 0));
Note, that Items implements IEnumerable only, so this query is represented as:
var q = Queryable.Select(queryable, x => Enumerable.Select<int, bool>(x.Items, y => y % 2 == 0));
Enumerable.Select takes Func<,> as its second parameters and we're expecting that this functor will be transformed into some method. But in this case, functor inside a Select method will be translated in Expressions as well:
The same could be used for creating your own Expressions - if you use methods that accept functors, do not compile them in place, just insert as Expression.Lambda.ParameterExpression CS1 = Expression.Parameter(typeof(Foo), "x"); ParameterExpression CS3 = Expression.Parameter(typeof (int), "y"); MemberExpression memberExpression = Expression.Property(CS1, items); IQueryable<IEnumerable<bool>> q1 = queryable.Select( Expression.Lambda<Func<Foo, IEnumerable<bool>>>( Expression.Call(null, select, new Expression[] { memberExpression, Expression.Lambda<Func<int, bool>>( Expression.Equal( Expression.Modulo(CS3, Expression.Constant(2, typeof (int))), Expression.Constant(0, typeof (int))), new[] {CS3}) }), new[] {CS1}));
Note, that if Items implement IQueryable rather than IEnumerable, the nested Lamba expression will be quoted:
public class Bar { public IQueryable<int> Items { get; set; } }var queryable = new[] { new Bar {Items = new[] { 1, 2, 3 }.AsQueryable()} }.AsQueryable();
var q = queryable.Select(x => x.Items.Select(y => y % 2 == 0));
ParameterExpression CS1 = Expression.Parameter(typeof(Foo), "x"); ParameterExpression CS3 = Expression.Parameter(typeof (int), "y"); MemberExpression memberExpression = Expression.Property(CS1, items); IQueryable<IEnumerable<bool>> q1 = queryable.Select( Expression.Lambda<Func<Foo, IEnumerable<bool>>>( Expression.Call(null, select, new Expression[] { memberExpression, Expression.Quote( Expression.Lambda<Func<int, bool>>( Expression.Equal( Expression.Modulo(CS3, Expression.Constant(2, typeof (int))), Expression.Constant(0, typeof (int))), new[] {CS3}) ) }), new[] {CS1}));
And this is the only purpose for Expression.Quote method.
No comments:
Post a Comment