Ejemplo n.º 1
0
        public override object VisitSelectExpression(QueryFilteringParser.SelectExpressionContext context)
        {
            var properties = context.PROPERTYACCESS()
                             .Select(x => x.Symbol.Text)
                             .ToHashSet();

            var typeProperties = _parameter.Type
                                 .GetCashedProperties()
                                 .Where(p => properties.Contains(p.Name))
                                 .ToDictionary(p => p.Name, p => p.PropertyType);

            var dynamicType = DynamicTypeBuilder.CreateDynamicType(typeProperties);

            var propExpressions = properties.ToDictionary(x => x, x => new PropertyNode(x, _parameter).CreateExpression());

            var body = Expression.MemberInit(
                Expression.New(dynamicType.GetConstructors().Single()),
                dynamicType.GetFields().Select(f => Expression.Bind(f, propExpressions[f.Name])));

            var lambda = ReflectionCache.Lambda.MakeGenericMethod(
                typeof(Func <,>).MakeGenericType(_parameter.Type, dynamicType));

            var expression = lambda.Invoke(null, new object[] { body, new ParameterExpression[] { _parameter } });

            var select = ReflectionCache.Select
                         .MakeGenericMethod(_parameter.Type, dynamicType);

            return(select.Invoke(null, new [] { _sourceQueryable, expression }));
        }
 /// <summary>
 /// Visit a parse tree produced by <see cref="QueryFilteringParser.selectExpression"/>.
 /// <para>
 /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
 /// on <paramref name="context"/>.
 /// </para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 /// <return>The visitor result.</return>
 public virtual Result VisitSelectExpression([NotNull] QueryFilteringParser.SelectExpressionContext context)
 {
     return(VisitChildren(context));
 }