/// <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 materializationExpression, int[] indexMap = null) { if (!entityType.HasClrType()) { throw new InvalidOperationException(CoreStrings.NoClrType(entityType.DisplayName())); } if (entityType.IsAbstract()) { throw new InvalidOperationException(CoreStrings.CannotMaterializeAbstractType(entityType)); } var constructorBinding = (ConstructorBinding)entityType[CoreAnnotationNames.ConstructorBinding]; if (constructorBinding == null) { var constructorInfo = entityType.ClrType.GetDeclaredConstructor(null); if (constructorInfo == null) { throw new InvalidOperationException(CoreStrings.NoParameterlessConstructor(entityType.DisplayName())); } constructorBinding = new DirectConstructorBinding(constructorInfo, Array.Empty <ParameterBinding>()); } // This is to avoid breaks because this method used to expect ValueBuffer but now expects MaterializationContext var valueBufferExpression = materializationExpression; if (valueBufferExpression.Type == typeof(MaterializationContext)) { valueBufferExpression = Expression.Call(materializationExpression, MaterializationContext.GetValueBufferMethod); } else { materializationExpression = Expression.New(MaterializationContext.ObsoleteConstructor, materializationExpression); } var bindingInfo = new ParameterBindingInfo( entityType, materializationExpression, indexMap); var properties = new HashSet <IPropertyBase>( entityType.GetServiceProperties().Cast <IPropertyBase>() .Concat( entityType .GetProperties() .Where(p => !p.IsShadowProperty))); foreach (var consumedProperty in constructorBinding .ParameterBindings .SelectMany(p => p.ConsumedProperties)) { properties.Remove(consumedProperty); } var constructorExpression = constructorBinding.CreateConstructorExpression(bindingInfo); if (properties.Count == 0) { return(constructorExpression); } var instanceVariable = Expression.Variable(constructorBinding.RuntimeType, "instance"); var blockExpressions = new List <Expression> { Expression.Assign( instanceVariable, constructorExpression) }; var indexerPropertyInfo = entityType.EFIndexerProperty(); foreach (var property in properties) { var memberInfo = property.GetMemberInfo(forConstruction: true, forSet: true); var readValueExpression = property is IServiceProperty serviceProperty ? serviceProperty.GetParameterBinding().BindToParameter(bindingInfo) : CreateReadValueExpression( valueBufferExpression, memberInfo.GetMemberType(), indexMap?[property.GetIndex()] ?? property.GetIndex(), property); blockExpressions.Add( property.IsIndexedProperty ? Expression.Assign( Expression.MakeIndex( instanceVariable, indexerPropertyInfo, new[] { Expression.Constant(property.Name) }), readValueExpression) : Expression.MakeMemberAccess( instanceVariable, memberInfo).Assign( readValueExpression)); } blockExpressions.Add(instanceVariable); return(Expression.Block(new[] { instanceVariable }, blockExpressions)); }