Exemple #1
0
        private static void AddAutoRegisteredTypes(Bootstrapper bootstrapper, IServiceCollection services, string[] excludedDllsForAutoRegistration)
        {
            bool CheckPublicConstructorAvailability(Type type)
            {
                if (type.GetConstructors().Any(c => c.IsPublic))
                {
                    return(true);
                }
                bootstrapper.AddNotification(new BootstrapperNotification(BootstrapperNotificationType.Error, "You must provide public constructor to Microsoft.Extensions.DependencyInjection extension cause it only supports public constructor. If you want to use internal or private constructor, switch to another IoC provider that supports this feature."));
                return(false);
            }

            foreach (var type in ReflectionTools.GetAllTypes(excludedDllsForAutoRegistration)
                     .Where(t => typeof(IAutoRegisterType).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList())
            {
                if (!CheckPublicConstructorAvailability(type))
                {
                    continue;
                }

                services.AddTransient(type, type);
                foreach (var @interface in type.GetInterfaces())
                {
                    services.AddTransient(@interface, type);
                }
            }

            foreach (var type in ReflectionTools.GetAllTypes(excludedDllsForAutoRegistration)
                     .Where(t => typeof(IAutoRegisterTypeSingleInstance).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList())
            {
                if (!CheckPublicConstructorAvailability(type))
                {
                    continue;
                }

                services.AddSingleton(type, type);
                foreach (var @interface in type.GetInterfaces())
                {
                    services.AddSingleton(@interface, type);
                }
            }
        }
        /// <summary>
        /// Configure EF Core as repository implementation.
        /// This methods uses a single database configuration and create dynamically all context
        /// from every concerned assembly.
        /// </summary>
        /// <param name="bootstrapper">Bootstrapper instance</param>
        /// <param name="optionsBuilderCfg">Options builder configuration lambda.</param>
        /// <param name="options">Custom options to use of using EF.</param>
        public static Bootstrapper UseEFCoreAsMainRepository(this Bootstrapper bootstrapper, Action <DbContextOptionsBuilder> optionsBuilderCfg,
                                                             EFCoreOptions options = null)
        {
            if (optionsBuilderCfg == null)
            {
                throw new ArgumentNullException(nameof(optionsBuilderCfg));
            }

            InitializeBootstrapperService(
                bootstrapper,
                (ctx) =>
            {
                if (ctx.IsServiceRegistered(BootstrapperServiceType.IoC))
                {
                    var dbContextOptionsBuilder = new DbContextOptionsBuilder();
                    optionsBuilderCfg(dbContextOptionsBuilder);


                    var customDbContexts = ReflectionTools.GetAllTypes().Where(t => t.IsInHierarchySubClassOf(typeof(BaseDbContext)) && !t.IsAbstract && t.IsClass && t != typeof(BaseDbContext));
                    if (customDbContexts.Any())
                    {
                        foreach (var customDbContextType in customDbContexts)
                        {
                            bootstrapper.AddIoCRegistration(new TypeRegistration(customDbContextType, true));
                            var customDbContextOptionsType = typeof(DbContextOptions <>).MakeGenericType(customDbContextType);
                            bootstrapper.AddIoCRegistration(new InstanceTypeRegistration(dbContextOptionsBuilder.Options, typeof(DbContextOptions), customDbContextOptionsType));
                            bootstrapper.AddIoCRegistration(new FactoryRegistration((scope) =>
                            {
                                return(new EFCoreDataReaderAdapter(scope.Resolve(customDbContextType) as BaseDbContext, options));
                            },
                                                                                    typeof(EFCoreDataReaderAdapter),
                                                                                    typeof(IDataReaderAdapter)));
                            bootstrapper.AddIoCRegistration(new FactoryRegistration((scope) =>
                            {
                                return(new EFCoreDataWriterAdapter(scope.Resolve(customDbContextType) as BaseDbContext, options));
                            },
                                                                                    typeof(EFCoreDataWriterAdapter),
                                                                                    typeof(IDataWriterAdapter)));
                        }
                    }
                    else
                    {
                        bootstrapper.AddIoCRegistration(new TypeRegistration(typeof(BaseDbContext), typeof(BaseDbContext)));
                        bootstrapper.AddIoCRegistration(new TypeRegistration <EFCoreDataReaderAdapter>(true));
                        bootstrapper.AddIoCRegistration(new TypeRegistration <EFCoreDataWriterAdapter>(true));
                        bootstrapper.AddIoCRegistration(new InstanceTypeRegistration(dbContextOptionsBuilder.Options, typeof(DbContextOptions), typeof(DbContextOptions <BaseDbContext>)));
                    }

                    if (options != null)
                    {
                        bootstrapper.AddIoCRegistration(new InstanceTypeRegistration(options, typeof(EFCoreOptions)));
                    }


                    foreach (var item in ReflectionTools.GetAllTypes().Where(t => typeof(IPersistableEntity).IsAssignableFrom(t) && !t.IsAbstract && t.IsClass).ToList())
                    {
                        var efRepoType         = typeof(EFRepository <>).MakeGenericType(item);
                        var dataReaderRepoType = typeof(IDataReaderRepository <>).MakeGenericType(item);
                        var databaseRepoType   = typeof(IDatabaseRepository <>).MakeGenericType(item);
                        var dataUpdateRepoType = typeof(IDataUpdateRepository <>).MakeGenericType(item);

                        Type ctxType = null;

                        if (s_ContextTypesPerAssembly.ContainsKey(item.Assembly.FullName))
                        {
                            ctxType = s_ContextTypesPerAssembly[item.Assembly.FullName];
                        }
                        else
                        {
                            ctxType = ReflectionTools
                                      .GetAllTypes()
                                      .Where(t => t.Assembly.FullName == item.Assembly.FullName)
                                      .FirstOrDefault(c => c.IsSubclassOf(typeof(BaseDbContext)));
                            s_ContextTypesPerAssembly[item.Assembly.FullName] = ctxType;

                            bootstrapper
                            .AddIoCRegistration(new FactoryRegistration(() => ctxType.CreateInstance(dbContextOptionsBuilder.Options), ctxType));
                        }

                        if (ctxType == null)
                        {
                            throw new InvalidOperationException("Bootstrapper.UseEFCoreAsMainRepository() : " +
                                                                $"No DbContext found for assembly {item.Assembly.FullName}, but this assembly contains a " +
                                                                "some persistence entities. You need to create a specific class that inherits from BaseDbContext in this assembly to use this configuration method.");
                        }

                        bootstrapper
                        .AddIoCRegistration(new FactoryRegistration(() =>
                        {
                            var dbCtx = ctxType.CreateInstance(dbContextOptionsBuilder.Options);
                            return(efRepoType.CreateInstance(dbCtx));
                        },
                                                                    efRepoType, dataUpdateRepoType, databaseRepoType, dataReaderRepoType));
                    }
                }
                else
                {
                    bootstrapper.AddNotification(new Bootstrapping.Notifications.BootstrapperNotification(Bootstrapping.Notifications.BootstrapperNotificationType.Warning,
                                                                                                          "No IoC has been configured in your system, it means that all EF DAL will no works 'automatically'," +
                                                                                                          " you will need to use it with EFCoreDataReaderAdapter and EFCoreDataWriterAdapter with the RepositoryBase class. " +
                                                                                                          "While this will work, it's not a recommended option and configuring IoC should be strongly considered."));
                }
            }, options);
            return(bootstrapper);
        }