private ExtendedNewExpression CreateNewExpression(IEntityType type, DirectConstructorBinding directConstructorBinding, BaseTableExpression table, Func <IProperty, Expression> makeColumnExpression) { var constructor = directConstructorBinding.Constructor; var arguments = new Expression[constructor.GetParameters().Length]; var readableMembers = new MemberInfo[arguments.Length]; var writableMembers = new MemberInfo[arguments.Length]; for (var i = 0; i < arguments.Length; i++) { var binding = directConstructorBinding.ParameterBindings[i]; arguments[i] = GetBindingExpression(type, binding, makeColumnExpression); if (binding.ConsumedProperties.ElementAtOrDefault(0) is IPropertyBase property) { readableMembers[i] = property.GetReadableMemberInfo(); writableMembers[i] = property.GetWritableMemberInfo(); } } return(new ExtendedNewExpression(constructor, arguments, readableMembers, writableMembers)); }
public static string GetStringConstructorOfDirectConstructorBinding(DirectConstructorBinding directConstructorBinding) { var sb = new StringBuilder(); var v = directConstructorBinding.Constructor.GetType(); if (directConstructorBinding.ParameterBindings.Count > 0) { throw new Exception("Parameterbinding not written"); } // directConstructorBinding.Constructor.DeclaringType var splitFullName = directConstructorBinding.Constructor.DeclaringType.FullName.Split("`"); string typeFullName = splitFullName.First(); if (splitFullName.Length > 1) { typeFullName += "<string>"; } sb.AppendFormat( "new DirectConstructorBinding(typeof({0}).GetDeclaredConstructor(null),new List<ParameterBinding>())", typeFullName); return(sb.ToString()); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public virtual Expression CreateMaterializeExpression( IEntityType entityType, string entityInstanceName, 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, entityInstanceName); var blockExpressions = new List <Expression> { Expression.Assign( instanceVariable, constructorExpression) }; var indexerPropertyInfo = entityType.FindIndexerProperty(); 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)); }