Beispiel #1
0
        private bool IsCandidateNavigationPropertyType(
            Type targetType,
            MemberInfo memberInfo,
            Model model,
            out bool?shouldBeOwned)
        {
            shouldBeOwned = null;
            var configuration            = model.Configuration;
            var configurationType        = configuration?.GetConfigurationType(targetType);
            var isConfiguredAsEntityType = configurationType.IsEntityType();

            if (isConfiguredAsEntityType == false ||
                !targetType.IsValidEntityType())
            {
                return(false);
            }

            if (configurationType != null)
            {
                shouldBeOwned = configurationType == TypeConfigurationType.OwnedEntityType;
            }

            return(isConfiguredAsEntityType == true ||
                   (targetType != typeof(object) &&
                    _parameterBindingFactories.FindFactory(memberInfo.GetMemberType(), memberInfo.GetSimpleMemberName()) == null &&
                    _typeMappingSource.FindMapping(targetType, model) == null));
        }
Beispiel #2
0
        private void Process(IConventionEntityTypeBuilder entityTypeBuilder)
        {
            var entityType = entityTypeBuilder.Metadata;

            if (!entityType.HasClrType())
            {
                return;
            }

            var candidates = entityType.GetRuntimeProperties().Values;

            foreach (var propertyInfo in candidates)
            {
                if (entityTypeBuilder.IsIgnored(propertyInfo.GetSimpleMemberName()) ||
                    ConventionEntityTypeExtensions.FindProperty(entityType, propertyInfo) != null ||
                    entityType.FindNavigation(propertyInfo) != null ||
                    !propertyInfo.IsCandidateProperty(publicOnly: false) ||
                    (propertyInfo.IsCandidateProperty() &&
                     _typeMappingSource.FindMapping(propertyInfo) != null))
                {
                    continue;
                }

                var factory = _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName());
                if (factory == null)
                {
                    continue;
                }

                var duplicateMap = GetDuplicateServiceProperties(entityType);
                if (duplicateMap != null &&
                    duplicateMap.TryGetValue(propertyInfo.PropertyType, out var duplicateServiceProperties))
                {
                    duplicateServiceProperties.Add(propertyInfo);

                    return;
                }

                var otherServicePropertySameType = entityType.GetServiceProperties()
                                                   .FirstOrDefault(p => p.ClrType == propertyInfo.PropertyType);
                if (otherServicePropertySameType != null)
                {
                    if (ConfigurationSource.Convention.Overrides(otherServicePropertySameType.GetConfigurationSource()))
                    {
                        otherServicePropertySameType.DeclaringEntityType.RemoveServiceProperty(otherServicePropertySameType.Name);
                    }

                    AddDuplicateServiceProperty(entityTypeBuilder, propertyInfo);
                    AddDuplicateServiceProperty(entityTypeBuilder, otherServicePropertySameType.GetIdentifyingMemberInfo());

                    return;
                }

                entityTypeBuilder.ServiceProperty(propertyInfo)?.HasParameterBinding(
                    (ServiceParameterBinding)factory.Bind(entityType, propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName()));
            }
        }
        public static Type FindCandidateNavigationPropertyType(
            this PropertyInfo propertyInfo,
            ITypeMappingSource typeMappingSource,
            IParameterBindingFactories parameterBindingFactories)
        {
            var targetType         = propertyInfo.PropertyType;
            var targetSequenceType = targetType.TryGetSequenceType();

            if (!propertyInfo.IsCandidateProperty(targetSequenceType == null))
            {
                return(null);
            }

            targetType = targetSequenceType ?? targetType;
            targetType = targetType.UnwrapNullableType();

            if (targetType.GetTypeInfo().IsInterface ||
                targetType.GetTypeInfo().IsValueType ||
                targetType == typeof(object) ||
                parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.Name) != null ||
                typeMappingSource.FindMapping(targetType) != null)
            {
                return(null);
            }

            return(targetType);
        }
        private bool TryBindConstructor(
            IEntityType entityType,
            ConstructorInfo constructor,
            Func <IParameterBindingFactory, IEntityType, Type, string, ParameterBinding> bind,
            out InstantiationBinding binding,
            out IEnumerable <ParameterInfo> unboundParameters)
        {
            IEnumerable <(ParameterInfo Parameter, ParameterBinding Binding)> bindings
                = constructor.GetParameters().Select(
                      p => (p, string.IsNullOrEmpty(p.Name)
                            ? null
                            : _propertyFactory.FindParameter(entityType, p.ParameterType, p.Name)
                            ?? bind(_factories.FindFactory(p.ParameterType, p.Name), entityType, p.ParameterType, p.Name)))
                  .ToList();

            if (bindings.Any(b => b.Binding == null))
            {
                unboundParameters = bindings.Where(b => b.Binding == null).Select(b => b.Parameter);
                binding           = null;

                return(false);
            }

            unboundParameters = null;
            binding           = new ConstructorBinding(constructor, bindings.Select(b => b.Binding).ToList());

            return(true);
        }
        /// <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 bool TryBindConstructor(
            IConventionEntityType entityType,
            ConstructorInfo constructor,
            out InstantiationBinding binding,
            out IEnumerable <ParameterInfo> unboundParameters)
        {
            IEnumerable <(ParameterInfo Parameter, ParameterBinding Binding)> bindings
                = constructor.GetParameters().Select(
                      p => (p, _propertyFactory.TryBindParameter(entityType, p.ParameterType, p.Name)
                            ?? _factories.FindFactory(p.ParameterType, p.Name)?.Bind(entityType, p.ParameterType, p.Name)))
                  .ToList();

            if (bindings.Any(b => b.Binding == null))
            {
                unboundParameters = bindings.Where(b => b.Binding == null).Select(b => b.Parameter);
                binding           = null;

                return(false);
            }

            unboundParameters = null;
            binding           = new ConstructorBinding(constructor, bindings.Select(b => b.Binding).ToList());

            return(true);
        }
        /// <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 Type FindCandidateNavigationPropertyType(MemberInfo memberInfo)
        {
            Check.NotNull(memberInfo, nameof(memberInfo));

            var targetType         = memberInfo.GetMemberType();
            var targetSequenceType = targetType.TryGetSequenceType();

            if (!(memberInfo is PropertyInfo propertyInfo) ||
                !propertyInfo.IsCandidateProperty(targetSequenceType == null))
            {
                return(null);
            }

            targetType = targetSequenceType ?? targetType;
            targetType = targetType.UnwrapNullableType();

            return(targetType.GetTypeInfo().IsInterface ||
                   targetType.GetTypeInfo().IsValueType ||
                   targetType == typeof(object) ||
                   _parameterBindingFactories.FindFactory(targetType, memberInfo.GetSimpleMemberName()) != null ||
                   _typeMappingSource.FindMapping(targetType) != null ||
                   targetType.GetTypeInfo().IsArray
                ? null
                : targetType);
        }
        /// <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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            if (entityType.HasClrType())
            {
                var candidates = entityType.ClrType.GetRuntimeProperties();

                foreach (var propertyInfo in candidates)
                {
                    if (!(propertyInfo.IsCandidateProperty() &&
                          _typeMapper.FindMapping(propertyInfo) != null) &&
                        propertyInfo.IsCandidateProperty(publicOnly: false))
                    {
                        var factory = _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.Name);

                        if (factory != null)
                        {
                            var serviceProperty = entityType.FindServiceProperty(propertyInfo.Name);
                            if (serviceProperty == null ||
                                serviceProperty.PropertyInfo != propertyInfo)
                            {
                                serviceProperty = entityType.AddServiceProperty(propertyInfo, ConfigurationSource.Convention);
                            }

                            serviceProperty.SetParameterBinding(
                                (ServiceParameterBinding)factory.Bind(entityType, propertyInfo.PropertyType, propertyInfo.Name));
                        }
                    }
                }
            }

            return(entityTypeBuilder);
        }
        /// <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 Type FindCandidateNavigationPropertyType(PropertyInfo propertyInfo)
        {
            Check.NotNull(propertyInfo, nameof(propertyInfo));

            var targetType         = propertyInfo.PropertyType;
            var targetSequenceType = targetType.TryGetSequenceType();

            if (!propertyInfo.IsCandidateProperty(targetSequenceType == null))
            {
                return(null);
            }

            targetType = targetSequenceType ?? targetType;
            targetType = targetType.UnwrapNullableType();

            if (targetType.GetTypeInfo().IsInterface ||
                targetType.GetTypeInfo().IsValueType ||
                targetType == typeof(object) ||
                _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.Name) != null ||
                _typeMappingSource.FindMapping(targetType) != null)
            {
                return(null);
            }

            return(targetType);
        }
Beispiel #9
0
        /// <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 Type?FindCandidateNavigationPropertyType(MemberInfo memberInfo, ModelConfiguration?configuration)
        {
            var targetType         = memberInfo.GetMemberType();
            var targetSequenceType = targetType.TryGetSequenceType();

            if (!(memberInfo is PropertyInfo propertyInfo) ||
                !propertyInfo.IsCandidateProperty(targetSequenceType == null))
            {
                return(null);
            }

            var isConfiguredAsEntityType = configuration?.GetConfigurationType(targetType).IsEntityType();

            if (isConfiguredAsEntityType == false)
            {
                return(null);
            }

            if (targetSequenceType != null)
            {
                isConfiguredAsEntityType ??= configuration?.GetConfigurationType(targetSequenceType).IsEntityType();
                if (isConfiguredAsEntityType == false)
                {
                    return(null);
                }
            }

            targetType = targetSequenceType ?? targetType;
            if (!targetType.IsValidEntityType())
            {
                return(null);
            }

            targetType = targetType.UnwrapNullableType();
            return(isConfiguredAsEntityType == null &&
                   (targetType == typeof(object) ||
                    _parameterBindingFactories.FindFactory(targetType, memberInfo.GetSimpleMemberName()) != null ||
                    _typeMappingSource.FindMapping(targetType) != null)
                    ? null
                    : targetType);
        }
        /// <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 InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder)
        {
            Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
            var entityType = entityTypeBuilder.Metadata;

            if (!entityType.HasClrType())
            {
                return(entityTypeBuilder);
            }

            var candidates = entityType.ClrType.GetRuntimeProperties();

            foreach (var propertyInfo in candidates)
            {
                if (entityTypeBuilder.IsIgnored(propertyInfo.Name, ConfigurationSource.Convention) ||
                    entityType.FindProperty(propertyInfo) != null ||
                    entityType.FindNavigation(propertyInfo) != null ||
                    !propertyInfo.IsCandidateProperty(publicOnly: false) ||
                    (propertyInfo.IsCandidateProperty() &&
                     _typeMappingSource.FindMapping(propertyInfo) != null))
                {
                    continue;
                }

                var factory = _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.Name);
                if (factory == null)
                {
                    continue;
                }

                var duplicateMap = GetDuplicateServiceProperties(entityType);
                if (duplicateMap != null &&
                    duplicateMap.TryGetValue(propertyInfo.PropertyType, out var duplicateServiceProperties))
                {
                    duplicateServiceProperties.Add(propertyInfo);

                    return(entityTypeBuilder);
                }

                var otherServicePropertySameType = entityType.GetServiceProperties()
                                                   .FirstOrDefault(p => p.ClrType == propertyInfo.PropertyType);
                if (otherServicePropertySameType != null)
                {
                    if (ConfigurationSource.Convention.Overrides(otherServicePropertySameType.GetConfigurationSource()))
                    {
                        otherServicePropertySameType.DeclaringEntityType.RemoveServiceProperty(otherServicePropertySameType.Name);
                    }

                    AddDuplicateServiceProperty(entityTypeBuilder, propertyInfo);
                    AddDuplicateServiceProperty(entityTypeBuilder, otherServicePropertySameType.GetIdentifyingMemberInfo());

                    return(entityTypeBuilder);
                }

                entityTypeBuilder.ServiceProperty(propertyInfo, ConfigurationSource.Convention)?.SetParameterBinding(
                    (ServiceParameterBinding)factory.Bind(entityType, propertyInfo.PropertyType, propertyInfo.Name),
                    ConfigurationSource.Convention);
            }

            return(entityTypeBuilder);
        }