public void MemberInitExpressionForDerivedTypeCanBeUsedWithPropertyTypedAsBaseType()
        {
            Expression <Func <Cook, Result <BaseValue> > > lambaExpression =
                c => new Result <BaseValue> {
                Value = new DerivedValue {
                    StringValue = c.FirstName
                }
            };

            // new Result { ... }
            var resultInitExpression = ((MemberInitExpression)lambaExpression.Body);
            // BaseValue = new DerivedValue { ... }
            var derivedValueMemberAssignment = ((MemberAssignment)resultInitExpression.Bindings[0]);
            // new DerivedValue { ... }
            var derivedValueInitExpression = (MemberInitExpression)(derivedValueMemberAssignment.Expression);
            // StringValue = c.FirstName
            var derivedValueStringValueMemberAssignment = ((MemberAssignment)derivedValueInitExpression.Bindings[0]);
            // c.FirstName
            var derivedValueStringValuePropertyExpression = (MemberExpression)derivedValueStringValueMemberAssignment.Expression;

            var inputParameter = Expression.Parameter(typeof(Result <BaseValue>), "input");

            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(
                searchedExpression: derivedValueStringValuePropertyExpression,
                fullExpression: resultInitExpression,
                inputParameter: inputParameter);

            Expression <Func <Result <BaseValue>, string> > expectedResult = input => ((DerivedValue)input.Value).StringValue;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
        public void NewExpressionForAnonymousType()
        {
            Expression <Func <Cook, dynamic> > lambaExpression = c => new { OuterValue = new { InnerValue = c.FirstName } };

            // new OuterType (...)
            var resultInitExpression = ((NewExpression)lambaExpression.Body);
            // new InnerType (...)
            var derivedValueInitExpression = (NewExpression)resultInitExpression.Arguments[0];
            // c.FirstName
            var derivedValueStringValuePropertyExpression = (MemberExpression)derivedValueInitExpression.Arguments[0];

            var inputParameter = Expression.Parameter(resultInitExpression.Type, "input");

            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(
                searchedExpression: derivedValueStringValuePropertyExpression,
                fullExpression: resultInitExpression,
                inputParameter: inputParameter);

            // Expression<Func<dynamic, string>> input => input.OuterValue.InnerValue;
            var expectedParameter = Expression.Parameter(resultInitExpression.Type, "input");

#if !NET_3_5
            var expectedOuterProperty = Expression.Property(expectedParameter, "OuterValue");
            var expectedInnerProperty = Expression.Property(expectedOuterProperty, "InnerValue");
            var expectedResult        = Expression.Lambda(expectedInnerProperty, expectedParameter);
#else
            var expectedOuterGetter = Expression.Call(expectedParameter, "get_OuterValue", new Type[0]);
            var expectedInnerGetter = Expression.Call(expectedOuterGetter, "get_InnerValue", new Type[0]);
            var expectedResult      = Expression.Lambda(expectedInnerGetter, expectedParameter);
#endif

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #3
0
        public void NestedNewExpression()
        {
            var outerAnonymousTypeCtor    = typeof(AnonymousType <int, AnonymousType>).GetConstructor(new[] { typeof(int), typeof(AnonymousType) });
            var outerAnonymousTypeAGetter = typeof(AnonymousType <int, AnonymousType>).GetMethod("get_a");
            var outerAnonymousTypeBGetter = typeof(AnonymousType <int, AnonymousType>).GetMethod("get_b");

#if !NET_3_5
            var outerAnonymousTypeBProperty = typeof(AnonymousType <int, AnonymousType>).GetProperty("b");
#endif

            // new AnonymousType (get_a = 2, get_b = new AnonymousType (get_a = _searchedExpression, get_b = 1))
            var innerExpression = Expression.New(
                _anonymousTypeCtorWithArgs,
                new[] { _searchedExpression, Expression.Constant(1) },
                _anonymousTypeAGetter,
                _anonymousTypeBGetter);
            var fullExpression = Expression.New(
                outerAnonymousTypeCtor,
                new Expression[] { Expression.Constant(2), innerExpression },
                outerAnonymousTypeAGetter,
                outerAnonymousTypeBGetter);
            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _nestedInputParameter);

            var inputParameter = Expression.Parameter(typeof(AnonymousType <int, AnonymousType>), "input");
            // input => input.get_b().get_a()
            var expectedResult = Expression.Lambda(
#if !NET_3_5
                Expression.MakeMemberAccess(Expression.MakeMemberAccess(inputParameter, outerAnonymousTypeBProperty), _anonymousTypeAProperty),
#else
                Expression.Call(Expression.Call(inputParameter, outerAnonymousTypeBGetter), _anonymousTypeAGetter),
#endif
                inputParameter);

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #4
0
        public void TrivialExpression()
        {
            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, _searchedExpression, _intInputParameter);

            Expression <Func <int, int> > expectedResult = input => input;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #5
0
        public void SearchedExpressionNotFound_AlthoughInOtherExpression()
        {
            var fullExpression = Expression.MemberInit(
                Expression.New(_anonymousTypeCtorWithoutArgs),
                Expression.Bind(_anonymousTypeAProperty, Expression.MakeBinary(ExpressionType.Add, _searchedExpression, _searchedExpression)),
                Expression.Bind(_anonymousTypeBProperty, Expression.Constant(1)));

            AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _simpleInputParameter);
        }
예제 #6
0
        public void ConvertExpression()
        {
            var parameter      = Expression.Parameter(typeof(long), "input");
            var fullExpression = Expression.Convert(_searchedExpression, typeof(long));
            var result         = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, parameter);

            Expression <Func <long, int> > expectedResult = input => (int)input;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #7
0
        public void TrivialExpression_WithEqualsTrue_ButNotReferenceEquals()
        {
            var searchedExpression1 = new QuerySourceReferenceExpression(ExpressionHelper.CreateMainFromClause <Cook>());
            var searchedExpression2 = new QuerySourceReferenceExpression(searchedExpression1.ReferencedQuerySource);

            var inputParameter = Expression.Parameter(typeof(Cook), "input");
            var result         = AccessorFindingExpressionVisitor.FindAccessorLambda(searchedExpression1, searchedExpression2, inputParameter);

            Expression <Func <Cook, Cook> > expectedResult = input => input;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #8
0
        public void SearchedExpressionNotFound_AlthoughInOtherMemberBinding()
        {
            var anonymousTypeListProperty = typeof(AnonymousType).GetProperty("List");
            var listAddMethod             = typeof(List <int>).GetMethod("Add");

            var fullExpression = Expression.MemberInit(
                Expression.New(_anonymousTypeCtorWithoutArgs),
                Expression.ListBind(anonymousTypeListProperty, Expression.ElementInit(listAddMethod, _searchedExpression)),
                Expression.Bind(_anonymousTypeBProperty, Expression.Constant(1)));

            AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _simpleInputParameter);
        }
예제 #9
0
        public void SimpleMemberBindingExpression()
        {
            // new AnonymousType() { a = _searchedExpression, b = 1 }
            var fullExpression = Expression.MemberInit(
                Expression.New(_anonymousTypeCtorWithoutArgs),
                Expression.Bind(_anonymousTypeAProperty, _searchedExpression),
                Expression.Bind(_anonymousTypeBProperty, Expression.Constant(1)));
            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _simpleInputParameter);

            Expression <Func <AnonymousType, int> > expectedResult = input => input.a;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #10
0
 private static ICollection <Func <TResult, object> > GetEntityAccessors <TResult>(
     IEnumerable <EntityTrackingInfo> entityTrackingInfos,
     Expression selector)
 => (from entityTrackingInfo in entityTrackingInfos
     select
         (Func <TResult, object>)
     AccessorFindingExpressionVisitor
     .FindAccessorLambda(
         entityTrackingInfo.QuerySourceReferenceExpression,
         selector,
         Expression.Parameter(typeof(TResult), "result"))
     .Compile())
 .ToList();
예제 #11
0
        protected virtual void IncludeNavigations(
            [NotNull] QueryModel queryModel,
            [NotNull] IReadOnlyCollection <IncludeSpecification> includeSpecifications)
        {
            Check.NotNull(queryModel, nameof(queryModel));
            Check.NotNull(includeSpecifications, nameof(includeSpecifications));

            var querySourceTracingExpressionVisitor
                = new QuerySourceTracingExpressionVisitor();

            foreach (var includeSpecification in includeSpecifications)
            {
                var resultQuerySourceReferenceExpression
                    = querySourceTracingExpressionVisitor
                      .FindResultQuerySourceReferenceExpression(
                          queryModel.SelectClause.Selector,
                          includeSpecification.QuerySource);

                if (resultQuerySourceReferenceExpression != null)
                {
                    var accessorLambda
                        = AccessorFindingExpressionVisitor
                          .FindAccessorLambda(
                              resultQuerySourceReferenceExpression,
                              queryModel.SelectClause.Selector,
                              Expression.Parameter(queryModel.SelectClause.Selector.Type));

                    QueryCompilationContext.Logger
                    .LogInformation(
                        includeSpecification.NavigationPath.Join("."),
                        Strings.LogIncludingNavigation);

                    IncludeNavigations(
                        includeSpecification,
                        _expression.Type.GetSequenceType(),
                        accessorLambda,
                        QuerySourceRequiresTracking(includeSpecification.QuerySource));

                    QueryCompilationContext
                    .AddTrackableInclude(
                        resultQuerySourceReferenceExpression.ReferencedQuerySource,
                        includeSpecification.NavigationPath);
                }
            }
        }
예제 #12
0
        protected virtual void IncludeNavigations(
            [NotNull] QueryModel queryModel,
            [NotNull] IReadOnlyCollection <IncludeSpecification> includeSpecifications)
        {
            Check.NotNull(queryModel, nameof(queryModel));
            Check.NotNull(includeSpecifications, nameof(includeSpecifications));

            foreach (var includeSpecification in includeSpecifications)
            {
                var resultQuerySourceReferenceExpression
                    = _querySourceTracingExpressionVisitorFactory
                      .Create()
                      .FindResultQuerySourceReferenceExpression(
                          queryModel.SelectClause.Selector,
                          includeSpecification.QuerySource);

                if (resultQuerySourceReferenceExpression != null)
                {
                    var accessorLambda
                        = AccessorFindingExpressionVisitor
                          .FindAccessorLambda(
                              resultQuerySourceReferenceExpression,
                              queryModel.SelectClause.Selector,
                              Expression.Parameter(queryModel.SelectClause.Selector.Type, "result"));

                    QueryCompilationContext.Logger
                    .LogVerbose(
                        CoreLoggingEventId.IncludingNavigation,
                        () => CoreStrings.LogIncludingNavigation(includeSpecification.NavigationPath.Join(".")));

                    IncludeNavigations(
                        includeSpecification,
                        _expression.Type.GetSequenceType(),
                        accessorLambda,
                        QueryCompilationContext.IsTrackingQuery);

                    QueryCompilationContext
                    .AddTrackableInclude(
                        resultQuerySourceReferenceExpression.ReferencedQuerySource,
                        includeSpecification.NavigationPath);
                }
            }
        }
예제 #13
0
        public void SimpleNewExpression()
        {
            // new AnonymousType (get_a = _searchedExpression, get_b = 1)
            var fullExpression = Expression.New(
                _anonymousTypeCtorWithArgs,
                new[] { _searchedExpression, Expression.Constant(1) },
                _anonymousTypeAGetter,
                _anonymousTypeBGetter);
            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _simpleInputParameter);

            var inputParameter = Expression.Parameter(typeof(AnonymousType), "input");
            var expectedResult = Expression.Lambda(
#if !NET_3_5
                Expression.MakeMemberAccess(inputParameter, _anonymousTypeAProperty),
#else
                Expression.Call(inputParameter, _anonymousTypeAGetter),
#endif
                inputParameter);

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #14
0
        public void NestedMemberBindingExpression()
        {
            var outerAnonymousTypeCtor      = typeof(AnonymousType <int, AnonymousType>).GetConstructor(Type.EmptyTypes);
            var outerAnonymousTypeAProperty = typeof(AnonymousType <int, AnonymousType>).GetProperty("a");
            var outerAnonymousTypeBProperty = typeof(AnonymousType <int, AnonymousType>).GetProperty("b");

            // new AnonymousType() { a = 2, b = new AnonymousType() { a = _searchedExpression, b = 1 } }
            var innerExpression = Expression.MemberInit(
                Expression.New(_anonymousTypeCtorWithoutArgs),
                Expression.Bind(_anonymousTypeAProperty, _searchedExpression),
                Expression.Bind(_anonymousTypeBProperty, Expression.Constant(1)));
            var fullExpression = Expression.MemberInit(
                Expression.New(outerAnonymousTypeCtor),
                Expression.Bind(outerAnonymousTypeAProperty, Expression.Constant(2)),
                Expression.Bind(outerAnonymousTypeBProperty, innerExpression));

            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _nestedInputParameter);

            Expression <Func <AnonymousType <int, AnonymousType>, int> > expectedResult = input => input.b.a;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #15
0
        public void NestedMemberBindingExpressionWithDerivedType()
        {
            var outerTypeCtor                = typeof(Result <BaseValue>).GetConstructor(Type.EmptyTypes);
            var outerTypeValueProperty       = typeof(Result <BaseValue>).GetProperty("Value");
            var innerTypeCtor                = typeof(DerivedValue).GetConstructor(Type.EmptyTypes);
            var innerTypeStringValueProperty = typeof(DerivedValue).GetProperty("StringValue");
            var searchedExpression           = Expression.Constant("a");
            var nestedInputParameter         = Expression.Parameter(typeof(Result <BaseValue>), "input");

            // new Result<BaseValue>() { Value = new DerivedValue() { StringValue = _searchedExpression } }
            var innerExpression = Expression.MemberInit(
                Expression.New(innerTypeCtor),
                Expression.Bind(innerTypeStringValueProperty, searchedExpression));
            var fullExpression = Expression.MemberInit(
                Expression.New(outerTypeCtor),
                Expression.Bind(outerTypeValueProperty, innerExpression));

            var result = AccessorFindingExpressionVisitor.FindAccessorLambda(searchedExpression, fullExpression, nestedInputParameter);

            Expression <Func <Result <BaseValue>, string> > expectedResult = input => ((DerivedValue)input.Value).StringValue;

            ExpressionTreeComparer.CheckAreEqualTrees(expectedResult, result);
        }
예제 #16
0
        public void SearchedExpressionNotFound_AlthoughInUnaryPlusExpression()
        {
            var fullExpression = Expression.UnaryPlus(_searchedExpression);

            AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _intInputParameter);
        }
예제 #17
0
        public void SearchedExpressionNotFound_AlthoughInNewExpressionWithoutMember()
        {
            var fullExpression = Expression.New(_anonymousTypeCtorWithArgs, _searchedExpression, _searchedExpression);

            AccessorFindingExpressionVisitor.FindAccessorLambda(_searchedExpression, fullExpression, _simpleInputParameter);
        }