public virtual Expression CreateMaterializeExpression(
            IEntityType entityType,
            Expression valueReaderExpression,
            int[] indexMap = null)
        {
            Check.NotNull(entityType, nameof(entityType));
            Check.NotNull(valueReaderExpression, nameof(valueReaderExpression));

            var materializer = entityType as IEntityMaterializer;

            if (materializer != null)
            {
                return(Expression.Call(
                           Expression.Constant(materializer),
                           ((Func <IValueReader, object>)materializer.CreateEntity).GetMethodInfo(),
                           valueReaderExpression));
            }

            if (!entityType.HasClrType())
            {
                throw new InvalidOperationException(Strings.NoClrType(entityType.Name));
            }

            if (entityType.IsAbstract)
            {
                throw new InvalidOperationException(Strings.CannotMaterializeAbstractType(entityType));
            }

            var instanceVariable = Expression.Variable(entityType.ClrType, "instance");

            var blockExpressions
                = new List <Expression>
                {
                Expression.Assign(
                    instanceVariable,
                    Expression.New(entityType.ClrType.GetDeclaredConstructor(null)))
                };

            blockExpressions.AddRange(
                from mapping in _memberMapper.MapPropertiesToMembers(entityType)
                let propertyInfo = mapping.Item2 as PropertyInfo
                                   let targetMember
                                       = propertyInfo != null
                        ? Expression.Property(instanceVariable, propertyInfo)
                        : Expression.Field(instanceVariable, (FieldInfo)mapping.Item2)
                                         select
                                         Expression.Assign(
                                             targetMember,
                                             CreateReadValueExpression(
                                                 valueReaderExpression,
                                                 targetMember.Type,
                                                 indexMap?[mapping.Item1.Index] ?? mapping.Item1.Index)));

            blockExpressions.Add(instanceVariable);

            return(Expression.Block(new[] { instanceVariable }, blockExpressions));
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual Expression CreateMaterializeExpression(
            IEntityType entityType,
            Expression valueBufferExpression,
            int[] indexMap = null)
        {
            // ReSharper disable once SuspiciousTypeConversion.Global
            var materializer = entityType as IEntityMaterializer;

            if (materializer != null)
            {
                return(Expression.Call(
                           Expression.Constant(materializer),
                           ((Func <ValueBuffer, object>)materializer.CreateEntity).GetMethodInfo(),
                           valueBufferExpression));
            }

            if (!entityType.HasClrType())
            {
                throw new InvalidOperationException(CoreStrings.NoClrType(entityType.Name));
            }

            if (entityType.IsAbstract())
            {
                throw new InvalidOperationException(CoreStrings.CannotMaterializeAbstractType(entityType));
            }

            var constructorInfo = entityType.ClrType.GetDeclaredConstructor(null);

            if (constructorInfo == null)
            {
                throw new InvalidOperationException(CoreStrings.NoParameterlessConstructor(entityType.DisplayName()));
            }

            var instanceVariable = Expression.Variable(entityType.ClrType, "instance");

            var blockExpressions
                = new List <Expression>
                {
                Expression.Assign(
                    instanceVariable,
                    Expression.New(constructorInfo))
                };

            blockExpressions.AddRange(
                from mapping in _memberMapper.MapPropertiesToMembers(entityType)
                let propertyInfo = mapping.Item2 as PropertyInfo
                                   let targetMember
                                       = propertyInfo != null
                        ? Expression.Property(instanceVariable, propertyInfo)
                        : Expression.Field(instanceVariable, (FieldInfo)mapping.Item2)
                                         select
                                         Expression.Assign(
                                             targetMember,
                                             CreateReadValueExpression(
                                                 valueBufferExpression,
                                                 targetMember.Type,
                                                 indexMap?[mapping.Item1.GetIndex()] ?? mapping.Item1.GetIndex())));

            blockExpressions.Add(instanceVariable);

            return(Expression.Block(new[] { instanceVariable }, blockExpressions));
        }