Exemplo n.º 1
0
        /// <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 InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
        {
            if (_options?.UseLazyLoadingProxies == true)
            {
                foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
                {
                    if (entityType.ClrType != null &&
                        !entityType.ClrType.IsAbstract)
                    {
                        if (entityType.ClrType.IsSealed)
                        {
                            throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
                        }

                        var binding = (ConstructorBinding)entityType[CoreAnnotationNames.ConstructorBinding];
                        if (binding == null)
                        {
                            _directBindingConvention.Apply(modelBuilder);
                        }

                        binding = (ConstructorBinding)entityType[CoreAnnotationNames.ConstructorBinding];

                        entityType[CoreAnnotationNames.ConstructorBinding] = RewriteToFactoryBinding(binding);

                        foreach (var navigation in entityType.GetNavigations())
                        {
                            if (navigation.PropertyInfo == null)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.FieldNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            if (!navigation.PropertyInfo.GetMethod.IsVirtual)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
                        }
                    }
                }
            }

            return(modelBuilder);
        }
        /// <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 InternalModelBuilder Apply(InternalModelBuilder modelBuilder)
        {
            if (_options?.UseLazyLoadingProxies == true)
            {
                foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
                {
                    if (entityType.ClrType?.IsAbstract == false)
                    {
                        if (entityType.ClrType.IsSealed)
                        {
                            throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
                        }

                        var proxyType = _proxyFactory.CreateLazyLoadingProxyType(entityType);

                        foreach (var conflictingProperty in entityType.GetDerivedTypes()
                                 .SelectMany(e => e.GetDeclaredServiceProperties().Where(p => p.ClrType == typeof(ILazyLoader)))
                                 .ToList())
                        {
                            conflictingProperty.DeclaringEntityType.RemoveServiceProperty(conflictingProperty.Name);
                        }

                        var serviceProperty = entityType.GetServiceProperties().FirstOrDefault(e => e.ClrType == typeof(ILazyLoader));
                        if (serviceProperty == null)
                        {
                            serviceProperty = entityType.AddServiceProperty(_lazyLoaderProperty, ConfigurationSource.Convention);
                            serviceProperty.SetParameterBinding(
                                (ServiceParameterBinding) new LazyLoaderParameterBindingFactory().Bind(
                                    entityType,
                                    typeof(ILazyLoader),
                                    nameof(IProxyLazyLoader.LazyLoader)));
                        }

                        var binding = (ConstructorBinding)entityType[CoreAnnotationNames.ConstructorBinding];
                        if (binding == null)
                        {
                            _directBindingConvention.Apply(modelBuilder);
                        }

                        binding = (ConstructorBinding)entityType[CoreAnnotationNames.ConstructorBinding];

                        entityType[CoreAnnotationNames.ConstructorBinding]
                            = new FactoryMethodConstructorBinding(
                                  _proxyFactory,
                                  _createLazyLoadingProxyMethod,
                                  new List <ParameterBinding>
                        {
                            new EntityTypeParameterBinding(),
                            new DefaultServiceParameterBinding(typeof(ILazyLoader), typeof(ILazyLoader), serviceProperty),
                            new ObjectArrayParameterBinding(binding.ParameterBindings)
                        },
                                  proxyType);

                        foreach (var navigation in entityType.GetNavigations())
                        {
                            if (navigation.PropertyInfo == null)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.FieldNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            if (!navigation.PropertyInfo.GetMethod.IsVirtual)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
                        }
                    }
                }
            }

            return(modelBuilder);
        }
        /// <summary>
        ///     Called after a model is finalized.
        /// </summary>
        /// <param name="modelBuilder"> The builder for the model. </param>
        /// <param name="context"> Additional information associated with convention execution. </param>
        public virtual void ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext <IConventionModelBuilder> context)
        {
            if (_options?.UseLazyLoadingProxies == true)
            {
                foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
                {
                    if (entityType.ClrType?.IsAbstract == false)
                    {
                        if (entityType.ClrType.IsSealed)
                        {
                            throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
                        }

                        var proxyType = _proxyFactory.CreateLazyLoadingProxyType(entityType);

                        foreach (var conflictingProperty in entityType.GetDerivedTypes()
                                 .SelectMany(e => e.GetDeclaredServiceProperties().Where(p => p.ClrType == typeof(ILazyLoader)))
                                 .ToList())
                        {
                            conflictingProperty.DeclaringEntityType.RemoveServiceProperty(conflictingProperty.Name);
                        }

                        var serviceProperty = entityType.GetServiceProperties().FirstOrDefault(e => e.ClrType == typeof(ILazyLoader));
                        if (serviceProperty == null)
                        {
                            serviceProperty = entityType.AddServiceProperty(_lazyLoaderProperty);
                            serviceProperty.SetParameterBinding(
                                (ServiceParameterBinding) new LazyLoaderParameterBindingFactory(_lazyLoaderParameterBindingFactoryDependencies)
                                .Bind(
                                    entityType,
                                    typeof(ILazyLoader),
                                    nameof(IProxyLazyLoader.LazyLoader)));
                        }

                        // WARNING: This code is EF internal; it should not be copied. See #10789 #14554
                        var binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];
                        if (binding == null)
                        {
                            _directBindingConvention.ProcessModelFinalized(modelBuilder, context);
                        }

                        // WARNING: This code is EF internal; it should not be copied. See #10789 #14554
                        binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding];

                        entityType.SetAnnotation(
                            // WARNING: This code is EF internal; it should not be copied. See #10789 #14554
                            CoreAnnotationNames.ConstructorBinding,
                            new FactoryMethodBinding(
                                _proxyFactory,
                                _createLazyLoadingProxyMethod,
                                new List <ParameterBinding>
                        {
                            new EntityTypeParameterBinding(),
                            new DependencyInjectionParameterBinding(typeof(ILazyLoader), typeof(ILazyLoader), serviceProperty),
                            new ObjectArrayParameterBinding(binding.ParameterBindings)
                        },
                                proxyType));

                        foreach (var navigation in entityType.GetNavigations())
                        {
                            if (navigation.PropertyInfo == null)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.FieldNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            if (!navigation.PropertyInfo.GetMethod.IsVirtual)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualNavigation(navigation.Name, entityType.DisplayName()));
                            }

                            navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
                        }
                    }
                }
            }
        }