Esempio n. 1
0
            public override Expression Visit(Expression node)
            {
                switch (node)
                {
                case DefaultIfEmptyExpression defaultIfEmptyExpression:
                {
                    return(Expression.Condition(
                               test: Expression.Call(
                                   readerParameter,
                                   isDBNullMethodInfo,
                                   Expression.Constant(readerIndex++)),
                               ifTrue: Expression.Default(defaultIfEmptyExpression.Type),
                               ifFalse: Visit(defaultIfEmptyExpression.Expression)));
                }

                case PolymorphicExpression polymorphicExpression:
                {
                    var variables   = new List <ParameterExpression>();
                    var expressions = new List <Expression>();

                    var rowValue              = polymorphicExpression.Row;
                    var rowVariable           = Expression.Variable(rowValue.Type, "row");
                    var rowParameterExpansion = (Expression)rowVariable;

                    if (rowValue is ExtraPropertiesExpression extraPropertiesExpression)
                    {
                        extraPropertiesExpression = VisitAndConvert(extraPropertiesExpression, nameof(Visit));

                        var properties = new List <Expression>();

                        for (var i = 0; i < extraPropertiesExpression.Names.Count; i++)
                        {
                            var propertyName     = extraPropertiesExpression.Names[i];
                            var propertyValue    = extraPropertiesExpression.Properties[i];
                            var propertyVariable = Expression.Variable(propertyValue.Type, propertyName);

                            variables.Add(propertyVariable);
                            properties.Add(propertyVariable);
                            expressions.Add(Expression.Assign(propertyVariable, propertyValue));
                        }

                        rowValue              = Visit(extraPropertiesExpression.Expression);
                        rowVariable           = Expression.Variable(rowValue.Type, "row");
                        rowParameterExpansion = extraPropertiesExpression.Update(rowVariable, properties);
                    }
                    else
                    {
                        rowValue = Visit(rowValue);
                    }

                    variables.Add(rowVariable);

                    expressions.Add(Expression.Assign(rowVariable, rowValue));

                    var useSwitchBlock
                        = polymorphicExpression.Descriptors
                          .All(d => d.Test.Body.NodeType == ExpressionType.Equal &&
                               ((BinaryExpression)d.Test.Body).Right is ConstantExpression constant &&
                               constant.Type.IsConstantLiteralType());

                    if (useSwitchBlock)
                    {
                        var result = Expression.Parameter(polymorphicExpression.Type);
                        var cases  = new SwitchCase[polymorphicExpression.Descriptors.Count()];
                        //var breakTarget = Expression.Label();
                        var i = 0;

                        foreach (var descriptor in polymorphicExpression.Descriptors)
                        {
                            var materializer = descriptor.Materializer.ExpandParameters(rowParameterExpansion);
                            var expansion    = Expression.Convert(materializer, polymorphicExpression.Type);
                            var assignment   = Expression.Assign(result, expansion);
                            var testValue    = ((BinaryExpression)descriptor.Test.Body).Right;
                            var body         = assignment; //Expression.Block(assignment, Expression.Break(breakTarget));

                            cases[i] = Expression.SwitchCase(body, testValue);
                            i++;
                        }

                        variables.Add(result);

                        expressions.Add(
                            Expression.Switch(
                                ((BinaryExpression)polymorphicExpression.Descriptors.First().Test.ExpandParameters(rowParameterExpansion)).Left,
                                Expression.Assign(result, Expression.Default(polymorphicExpression.Type)),
                                cases));

                        //expressions.Add(Expression.Label(breakTarget));
                        expressions.Add(result);
                    }
                    else
                    {
                        var result = Expression.Default(polymorphicExpression.Type) as Expression;

                        foreach (var descriptor in polymorphicExpression.Descriptors)
                        {
                            var test         = descriptor.Test.ExpandParameters(rowParameterExpansion);
                            var materializer = descriptor.Materializer.ExpandParameters(rowParameterExpansion);
                            var expansion    = Expression.Convert(materializer, polymorphicExpression.Type);

                            result = Expression.Condition(test, expansion, result, polymorphicExpression.Type);
                        }

                        expressions.Add(result);
                    }

                    return(Expression.Block(variables, expressions));
                }

                default:
                {
                    var visited = base.Visit(node);

                    if (visited is ExtraPropertiesExpression || visited is NewExpression)
                    {
                        return(visited);
                    }

                    var parts      = GetNameParts().ToArray();
                    var identifier = $"Materialize_";

                    if (parts.Length == 0)
                    {
                        identifier += "$root";
                    }
                    else if (parts.Length == 1)
                    {
                        identifier += parts[0];
                    }
                    else
                    {
                        identifier += $"{parts.First()}_{{{parts.Length - 2}}}_{parts.Last()}";
                    }

                    if (identifierCounts.TryGetValue(identifier, out var count))
                    {
                        identifierCounts[identifier] = count + 1;

                        identifier += $"_{count}";
                    }
                    else
                    {
                        identifierCounts[identifier] = 1;

                        identifier += "_0";
                    }

                    return(MaterializationUtilities.Invoke(visited, identifier));
                }
                }
            }
Esempio n. 2
0
        public override Expression Visit(Expression node)
        {
            switch (node)
            {
            case EntityMaterializationExpression entityMaterializationExpression:
            {
                var entityVariable           = Expression.Variable(node.Type, "entity");
                var shadowPropertiesVariable = Expression.Variable(typeof(object[]), "shadow");

                var entityType   = entityMaterializationExpression.EntityType;
                var materializer = Visit(entityMaterializationExpression.Expression);

                var getEntityMethodInfo = default(MethodInfo);

                switch (entityMaterializationExpression.IdentityMapMode)
                {
                case IdentityMapMode.StateManager:
                {
                    getEntityMethodInfo = EntityTrackingHelper.GetEntityUsingStateManagerMethodInfo;
                    break;
                }

                case IdentityMapMode.IdentityMap:
                default:
                {
                    getEntityMethodInfo = EntityTrackingHelper.GetEntityUsingIdentityMapMethodInfo;
                    break;
                }
                }

                var shadowPropertiesExpression = (Expression)Expression.Constant(new object[0]);
                var shadowProperties           = entityMaterializationExpression.ShadowProperties;

                if (!shadowProperties.IsDefaultOrEmpty)
                {
                    var values
                        = Enumerable
                          .Repeat(Expression.Constant(null), entityType.PropertyCount())
                          .Cast <Expression>()
                          .ToArray();

                    for (var i = 0; i < shadowProperties.Length; i++)
                    {
                        values[shadowProperties[i].GetIndex()]
                            = Expression.Convert(
                                  entityMaterializationExpression.Properties[i],
                                  typeof(object));
                    }

                    shadowPropertiesExpression = Expression.NewArrayInit(typeof(object), values);
                }

                var result
                    = Expression.Block(
                          variables: new ParameterExpression[]
                    {
                        entityVariable,
                        shadowPropertiesVariable,
                    },
                          expressions: new Expression[]
                    {
                        Expression.Assign(
                            shadowPropertiesVariable,
                            shadowPropertiesExpression),
                        Expression.Assign(
                            entityVariable,
                            new CollectionNavigationFixupExpressionVisitor(model)
                            .Visit(materializer)),
                        Expression.Convert(
                            Expression.Call(
                                getEntityMethodInfo,
                                Expression.Convert(executionContextParameter, typeof(EFCoreDbCommandExecutor)),
                                Expression.Constant(entityType),
                                entityMaterializationExpression.KeyExpression
                                .UnwrapLambda()
                                .ExpandParameters(entityVariable, shadowPropertiesVariable),
                                entityVariable,
                                shadowPropertiesVariable,
                                Expression.Constant(entityMaterializationExpression.IncludedNavigations.ToList())),
                            node.Type)
                    });

                var identifier = $"MaterializeEntity_{entityType.DisplayName()}";

                if (identifierCounts.TryGetValue(identifier, out var count))
                {
                    identifierCounts[identifier] = count + 1;

                    identifier += $"_{count}";
                }
                else
                {
                    identifierCounts[identifier] = 1;

                    identifier += "_0";
                }

                return(MaterializationUtilities.Invoke(result, identifier));
            }

            default:
            {
                return(base.Visit(node));
            }
            }
        }