コード例 #1
0
 public void Throws_if_non_virtual_indexer_property()
 {
     using var context = new ChangeContext <ChangeNonVirtualIndexer>(entityBuilderAction: b => b.IndexerProperty <int>("Snoopy"));
     Assert.Equal(
         ProxiesStrings.NonVirtualIndexerProperty(nameof(ChangeNonVirtualIndexer)),
         Assert.Throws <InvalidOperationException>(() => context.Model).Message);
 }
コード例 #2
0
 public void Throws_if_non_virtual_navigation()
 {
     using var context = new ChangeContext <ChangeNonVirtualNavEntity>();
     Assert.Equal(
         ProxiesStrings.NonVirtualProperty(nameof(ChangeNonVirtualNavEntity.SelfRef), nameof(ChangeNonVirtualNavEntity)),
         Assert.Throws <InvalidOperationException>(
             () => context.Model).Message);
 }
コード例 #3
0
ファイル: ProxyTests.cs プロジェクト: theolymp/efcore
 public void Throws_if_create_proxy_when_proxies_not_enabled()
 {
     using var context = new NeweyContextN7();
     Assert.Equal(
         ProxiesStrings.ProxiesNotEnabled(nameof(RedBullRb3)),
         Assert.Throws <InvalidOperationException>(
             () => context.CreateProxy <RedBullRb3>()).Message);
 }
コード例 #4
0
 public void Throws_if_sealed_class()
 {
     using var context = new ChangeContext <ChangeSealedEntity>();
     Assert.Equal(
         ProxiesStrings.ItsASeal(nameof(ChangeSealedEntity)),
         Assert.Throws <InvalidOperationException>(
             () => context.Model).Message);
 }
コード例 #5
0
 public void Throws_if_non_virtual_navigation()
 {
     using var context = new NeweyContextN2();
     Assert.Equal(
         ProxiesStrings.NonVirtualNavigation(nameof(McLarenMp419.SelfRef), nameof(McLarenMp419)),
         Assert.Throws <InvalidOperationException>(
             () => context.Model).Message);
 }
コード例 #6
0
 public void Throws_if_sealed_class()
 {
     using var context = new NeweyContextN1();
     Assert.Equal(
         ProxiesStrings.ItsASeal(nameof(McLarenMp418)),
         Assert.Throws <InvalidOperationException>(
             () => context.Model).Message);
 }
コード例 #7
0
    private static void CheckProxyOptions(IServiceProvider serviceProvider, string entityTypeName)
    {
        var options = serviceProvider.GetRequiredService <IDbContextOptions>().FindExtension <ProxiesOptionsExtension>();

        if (options?.UseProxies != true)
        {
            throw new InvalidOperationException(ProxiesStrings.ProxiesNotEnabled(entityTypeName));
        }
    }
コード例 #8
0
        public void Throws_if_dictionary_type_with_additional_properties()
        {
            using var context = new SharedChangeContext <Dictionary <string, int> >(b => b.IndexerProperty <int>("Snoopy"));

            Assert.Equal(
                ProxiesStrings.DictionaryCannotBeProxied(
                    typeof(Dictionary <string, int>).ShortDisplayName(), "STET (Dictionary<string, int>)",
                    typeof(IDictionary <string, int>).ShortDisplayName()),
                Assert.Throws <InvalidOperationException>(() => context.Model).Message);
        }
コード例 #9
0
        [ConditionalFact] // Issue #22407
        public void CreateProxy_throws_for_weak_entity_types()
        {
            using var context = new NeweyContext();

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundWeak(nameof(IsWeak)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy <IsWeak>()).Message);

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundWeak(nameof(IsWeak)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy <IsWeak>(_ => { })).Message);

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundWeak(nameof(IsWeak)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy(typeof(IsWeak))).Message);
        }
コード例 #10
0
ファイル: ProxyTests.cs プロジェクト: ebekker/efcore
        public void CreateProxy_throws_for_shared_type_entity_types_when_entity_type_name_not_known()
        {
            using var context = new NeweyContext();

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundShared(nameof(SharedTypeEntityType)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy <SharedTypeEntityType>()).Message);

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundShared(nameof(SharedTypeEntityType)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy <SharedTypeEntityType>(_ => { })).Message);

            Assert.Equal(
                ProxiesStrings.EntityTypeNotFoundShared(nameof(SharedTypeEntityType)),
                Assert.Throws <InvalidOperationException>(() => context.CreateProxy(typeof(SharedTypeEntityType))).Message);
        }
コード例 #11
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);
        }
コード例 #12
0
        private static object CreateProxy(
            this IServiceProvider serviceProvider,
            Type entityType,
            params object[] constructorArguments)
        {
            var options = serviceProvider.GetService <IDbContextOptions>().FindExtension <ProxiesOptionsExtension>();

            if (options?.UseProxies != true)
            {
                throw new InvalidOperationException(ProxiesStrings.ProxiesNotEnabled(entityType.ShortDisplayName()));
            }

            return(serviceProvider.GetService <IProxyFactory>().Create(
                       serviceProvider.GetService <ICurrentDbContext>().Context,
                       entityType,
                       constructorArguments));
        }
コード例 #13
0
        /// <summary>
        ///     Creates a proxy instance for an entity type if proxy creation has been turned on.
        /// </summary>
        /// <param name="context"> The <see cref="DbContext" />. </param>
        /// <param name="entityType"> The entity type for which a proxy is needed. </param>
        /// <param name="constructorArguments"> Arguments to pass to the entity type constructor. </param>
        /// <returns> The proxy instance. </returns>
        public static object CreateProxy(
            [NotNull] this DbContext context,
            [NotNull] Type entityType,
            [NotNull] params object[] constructorArguments)
        {
            Check.NotNull(context, nameof(context));
            Check.NotNull(entityType, nameof(entityType));
            Check.NotNull(constructorArguments, nameof(constructorArguments));

            var options = context.GetService <IDbContextOptions>().FindExtension <ProxiesOptionsExtension>();

            if (options?.UseLazyLoadingProxies != true)
            {
                throw new InvalidOperationException(ProxiesStrings.ProxiesNotEnabled(entityType.ShortDisplayName()));
            }

            return(context.GetService <IProxyFactory>().Create(context, entityType, constructorArguments));
        }
コード例 #14
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 object Create(
            DbContext context,
            Type type,
            params object[] constructorArguments)
        {
            var entityType = context.Model.FindRuntimeEntityType(type);

            if (entityType == null)
            {
                if (context.Model.IsShared(type))
                {
                    throw new InvalidOperationException(ProxiesStrings.EntityTypeNotFoundShared(type.ShortDisplayName()));
                }

                throw new InvalidOperationException(CoreStrings.EntityTypeNotFound(type.ShortDisplayName()));
            }

            return(CreateProxy(context, entityType, constructorArguments));
        }
コード例 #15
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?.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);
        }
コード例 #16
0
        public virtual void ProcessModelFinalizing(
            IConventionModelBuilder modelBuilder,
            IConventionContext <IConventionModelBuilder> context)
        {
            if (_options?.UseProxies == true)
            {
                foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
                {
                    var clrType = entityType.ClrType;
                    if (!clrType.IsAbstract)
                    {
                        if (clrType.IsSealed)
                        {
                            throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
                        }

                        var proxyType = _proxyFactory.CreateProxyType(_options, (IEntityType)entityType);

                        // WARNING: This code is EF internal; it should not be copied. See #10789 #14554
#pragma warning disable EF1001 // Internal EF Core API usage.
                        var binding = (InstantiationBinding?)entityType[CoreAnnotationNames.ConstructorBinding];
                        if (binding == null)
                        {
                            _directBindingConvention.ProcessModelFinalizing(modelBuilder, context);
                        }

                        binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding] !;
                        UpdateConstructorBindings(CoreAnnotationNames.ConstructorBinding, binding);

                        binding = (InstantiationBinding?)entityType[CoreAnnotationNames.ServiceOnlyConstructorBinding];
                        if (binding != null)
                        {
                            UpdateConstructorBindings(CoreAnnotationNames.ServiceOnlyConstructorBinding, binding);
                        }
#pragma warning restore EF1001 // Internal EF Core API usage.

                        foreach (var navigationBase in entityType.GetDeclaredNavigations()
                                 .Concat <IConventionNavigationBase>(entityType.GetDeclaredSkipNavigations()))
                        {
                            if (navigationBase.PropertyInfo == null)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.FieldProperty(navigationBase.Name, entityType.DisplayName()));
                            }

                            if (_options.UseChangeTrackingProxies &&
                                navigationBase.PropertyInfo.SetMethod?.IsReallyVirtual() == false)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualProperty(navigationBase.Name, entityType.DisplayName()));
                            }

                            if (_options.UseLazyLoadingProxies)
                            {
                                if (!navigationBase.PropertyInfo.GetMethod.IsReallyVirtual() &&
                                    (!(navigationBase is INavigation navigation &&
                                       navigation.ForeignKey.IsOwnership)))
                                {
                                    throw new InvalidOperationException(
                                              ProxiesStrings.NonVirtualProperty(navigationBase.Name, entityType.DisplayName()));
                                }

                                navigationBase.SetPropertyAccessMode(PropertyAccessMode.Field);
                            }
                        }

                        if (_options.UseChangeTrackingProxies)
                        {
                            var indexerChecked = false;
                            foreach (var property in entityType.GetDeclaredProperties()
                                     .Where(p => !p.IsShadowProperty()))
                            {
                                if (property.IsIndexerProperty())
                                {
                                    if (!indexerChecked)
                                    {
                                        indexerChecked = true;

                                        if (!property.PropertyInfo !.SetMethod.IsReallyVirtual())
                                        {
                                            if (clrType.IsGenericType &&
                                                clrType.GetGenericTypeDefinition() == typeof(Dictionary <,>) &&
                                                clrType.GenericTypeArguments[0] == typeof(string))
                                            {
                                                if (entityType.GetProperties().Any(p => !p.IsPrimaryKey()))
                                                {
                                                    throw new InvalidOperationException(
                                                              ProxiesStrings.DictionaryCannotBeProxied(
                                                                  clrType.ShortDisplayName(),
                                                                  entityType.DisplayName(),
                                                                  typeof(IDictionary <,>).MakeGenericType(clrType.GenericTypeArguments)
                                                                  .ShortDisplayName()));
                                                }
                                            }
                                            else
                                            {
                                                throw new InvalidOperationException(
                                                          ProxiesStrings.NonVirtualIndexerProperty(entityType.DisplayName()));
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    if (property.PropertyInfo == null)
                                    {
                                        throw new InvalidOperationException(
                                                  ProxiesStrings.FieldProperty(property.Name, entityType.DisplayName()));
                                    }

                                    if (property.PropertyInfo.SetMethod?.IsReallyVirtual() == false)
                                    {
                                        throw new InvalidOperationException(
                                                  ProxiesStrings.NonVirtualProperty(property.Name, entityType.DisplayName()));
                                    }
                                }
                            }
                        }

                        void UpdateConstructorBindings(string bindingAnnotationName, InstantiationBinding binding)
                        {
                            if (_options.UseLazyLoadingProxies)
                            {
                                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)));
                                }

                                entityType.SetAnnotation(
                                    bindingAnnotationName,
                                    new FactoryMethodBinding(
                                        _proxyFactory,
                                        _createLazyLoadingProxyMethod,
                                        new List <ParameterBinding>
                                {
                                    new ContextParameterBinding(typeof(DbContext)),
                                    new EntityTypeParameterBinding(),
                                    new DependencyInjectionParameterBinding(
                                        typeof(ILazyLoader), typeof(ILazyLoader), (IPropertyBase)serviceProperty),
                                    new ObjectArrayParameterBinding(binding.ParameterBindings)
                                },
                                        proxyType));
                            }
                            else
                            {
                                entityType.SetAnnotation(
                                    bindingAnnotationName,
                                    new FactoryMethodBinding(
                                        _proxyFactory,
                                        _createProxyMethod,
                                        new List <ParameterBinding>
                                {
                                    new ContextParameterBinding(typeof(DbContext)),
                                    new EntityTypeParameterBinding(),
                                    new ObjectArrayParameterBinding(binding.ParameterBindings)
                                },
                                        proxyType));
                            }
                        }
                    }
                }
            }
        }
コード例 #17
0
        /// <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?.UseProxies == 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.CreateProxyType(_options, entityType);

                        // 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];

                        if (_options.UseLazyLoadingProxies)
                        {
                            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)));
                            }

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

                            foreach (var prop in entityType.GetProperties().Where(p => !p.IsShadowProperty()))
                            {
                                if (prop.PropertyInfo == null)
                                {
                                    throw new InvalidOperationException(
                                              ProxiesStrings.FieldProperty(prop.Name, entityType.DisplayName()));
                                }

                                if (prop.PropertyInfo.SetMethod?.IsVirtual == false)
                                {
                                    throw new InvalidOperationException(
                                              ProxiesStrings.NonVirtualProperty(prop.Name, entityType.DisplayName()));
                                }
                            }
                        }

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

                            if (_options.UseChangeDetectionProxies &&
                                navigation.PropertyInfo.SetMethod?.IsVirtual == false)
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualProperty(navigation.Name, entityType.DisplayName()));
                            }

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

                                navigation.SetPropertyAccessMode(PropertyAccessMode.Field);
                            }
                        }
                    }
                }
            }
        }
コード例 #18
0
        /// <inheritdoc />
        public virtual void ProcessModelFinalizing(
            IConventionModelBuilder modelBuilder,
            IConventionContext <IConventionModelBuilder> context)
        {
            if (_options?.UseProxies == true)
            {
                foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
                {
                    var clrType = entityType.ClrType;
                    if (clrType.IsAbstract)
                    {
                        continue;
                    }

                    if (clrType.IsSealed)
                    {
                        throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
                    }

                    var proxyType = _proxyFactory.CreateProxyType(_options, entityType);

                    // WARNING: This code is EF internal; it should not be copied. See #10789 #14554
#pragma warning disable EF1001 // Internal EF Core API usage.
                    var binding = ((EntityType)entityType).ConstructorBinding;
                    if (binding == null)
                    {
                        _directBindingConvention.ProcessModelFinalizing(modelBuilder, context);
                        binding = ((EntityType)entityType).ConstructorBinding !;
                    }

                    ((EntityType)entityType).SetConstructorBinding(
                        UpdateConstructorBindings(entityType, proxyType, binding),
                        ConfigurationSource.Convention);

                    binding = ((EntityType)entityType).ServiceOnlyConstructorBinding;
                    if (binding != null)
                    {
                        ((EntityType)entityType).SetServiceOnlyConstructorBinding(
                            UpdateConstructorBindings(entityType, proxyType, binding),
                            ConfigurationSource.Convention);
                    }
#pragma warning restore EF1001 // Internal EF Core API usage.

                    foreach (var navigationBase in entityType.GetDeclaredNavigations()
                             .Concat <IConventionNavigationBase>(entityType.GetDeclaredSkipNavigations()))
                    {
                        if (navigationBase.PropertyInfo == null)
                        {
                            throw new InvalidOperationException(
                                      ProxiesStrings.FieldProperty(navigationBase.Name, entityType.DisplayName()));
                        }

                        if (_options.UseChangeTrackingProxies &&
                            navigationBase.PropertyInfo.SetMethod?.IsReallyVirtual() == false)
                        {
                            throw new InvalidOperationException(
                                      ProxiesStrings.NonVirtualProperty(navigationBase.Name, entityType.DisplayName()));
                        }

                        if (_options.UseLazyLoadingProxies)
                        {
                            if (!navigationBase.PropertyInfo.GetMethod !.IsReallyVirtual() &&
                                (!(navigationBase is INavigation navigation &&
                                   navigation.ForeignKey.IsOwnership)))
                            {
                                throw new InvalidOperationException(
                                          ProxiesStrings.NonVirtualProperty(navigationBase.Name, entityType.DisplayName()));
                            }

                            navigationBase.SetPropertyAccessMode(PropertyAccessMode.Field);
                        }
                    }

                    if (_options.UseChangeTrackingProxies)
                    {
                        var indexerChecked = false;
                        foreach (var property in entityType.GetDeclaredProperties()
                                 .Where(p => !p.IsShadowProperty()))
                        {
                            if (property.IsIndexerProperty())
                            {
                                if (!indexerChecked)
                                {
                                    indexerChecked = true;

                                    if (!property.PropertyInfo !.SetMethod !.IsReallyVirtual())
                                    {
                                        if (clrType.IsGenericType &&
                                            clrType.GetGenericTypeDefinition() == typeof(Dictionary <,>) &&
                                            clrType.GenericTypeArguments[0] == typeof(string))
                                        {
                                            if (entityType.GetProperties().Any(p => !p.IsPrimaryKey()))
                                            {
                                                throw new InvalidOperationException(
                                                          ProxiesStrings.DictionaryCannotBeProxied(
                                                              clrType.ShortDisplayName(),
                                                              entityType.DisplayName(),
                                                              typeof(IDictionary <,>).MakeGenericType(clrType.GenericTypeArguments)
                                                              .ShortDisplayName()));
                                            }
                                        }
                                        else
                                        {
                                            throw new InvalidOperationException(
                                                      ProxiesStrings.NonVirtualIndexerProperty(entityType.DisplayName()));
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (property.PropertyInfo == null)
                                {
                                    throw new InvalidOperationException(
                                              ProxiesStrings.FieldProperty(property.Name, entityType.DisplayName()));
                                }

                                if (property.PropertyInfo.SetMethod?.IsReallyVirtual() == false)
                                {
                                    throw new InvalidOperationException(
                                              ProxiesStrings.NonVirtualProperty(property.Name, entityType.DisplayName()));
                                }
                            }
                        }
                    }
                }
            }
        }