Exemplo n.º 1
0
        public void EventBusThrowsIfMessageNameIsNotCorrectlyFormatted()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Throws <ArgumentException>(() => eventBus.Notify("StubEventHandlerIncrement", new Dictionary <string, object>()));
        }
Exemplo n.º 2
0
        public void EventsAreCorrectlyDispatchedToEventHandlers()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Equal(0, stub1.Count);
            eventBus.Notify("ITestEventHandler.Increment", new Dictionary <string, object>());
            Assert.Equal(1, stub1.Count);
        }
Exemplo n.º 3
0
        public void NonStringNonEnumerableResultsAreTreatedLikeSelect()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            var results = eventBus.Notify("ITestEventHandler.GetInt", new Dictionary <string, object>()).Cast <int>();

            Assert.Equal(2, results.Count());
            Assert.Contains(1, results);
            Assert.Contains(2, results);
        }
Exemplo n.º 4
0
        public void StringResultsAreTreatedLikeSelect()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            var results = eventBus.Notify("ITestEventHandler.GetString", new Dictionary <string, object>()).Cast <string>();

            Assert.Equal(2, results.Count());
            Assert.Contains("Foo", results);
            Assert.Contains("Bar", results);
        }
Exemplo n.º 5
0
        public void EventHandlerWontBeCalledWhenNoParameterMatchExists2()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Equal(0, stub1.Result);
            Dictionary <string, object> arguments = new Dictionary <string, object>();

            eventBus.Notify("ITestEventHandler.Sum", arguments);
            Assert.Equal(0, stub1.Result);
        }
Exemplo n.º 6
0
        public void EventParametersAreCorrectlyPassedToExactlyMatchingMethodWhenThereIsOne2()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Equal(0, stub1.Result);
            Dictionary <string, object> arguments = new Dictionary <string, object>();

            arguments["a"] = 1000;
            eventBus.Notify("ITestEventHandler.Sum", arguments);
            Assert.Equal(3000, stub1.Result);
        }
Exemplo n.º 7
0
        public void EventParametersArePassedInCorrectOrderToEventHandlers()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Equal(0, stub1.Result);
            Dictionary <string, object> arguments = new Dictionary <string, object>();

            arguments["a"] = 2600;
            arguments["b"] = 5200;
            eventBus.Notify("ITestEventHandler.Substract", arguments);
            Assert.Equal(-2600, stub1.Result);
        }
Exemplo n.º 8
0
        public void EventParametersAreCorrectlyPassedToMatchingMethod()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Null(stub1.Summary);
            Dictionary <string, object> arguments = new Dictionary <string, object>();

            arguments["a"] = "a";
            arguments["b"] = "b";
            arguments["c"] = "c";
            eventBus.Notify("ITestEventHandler.Concat", arguments);
            Assert.Equal("abc", stub1.Summary);
        }
Exemplo n.º 9
0
        public void EnumerableResultsAreTreatedLikeSelectMany()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            var results = eventBus.Notify("ITestEventHandler.Gather", new Dictionary <string, object> {
                { "a", 42 }, { "b", "alpha" }
            }).Cast <string>();

            Assert.Equal(3, results.Count());
            Assert.Contains("42", results);
            Assert.Contains("alpha", results);
            Assert.Contains("[42,alpha]", results);
        }
Exemplo n.º 10
0
        public void EventParametersAreCorrectlyPassedToBestMatchingMethodAndExtraParametersAreIgnored()
        {
            var stub1    = new StubEventHandler();
            var stub2    = new StubEventHandler2();
            var eventBus = new DefaultOrchardEventBus(new IEventHandler[] { stub1, stub2 });

            Assert.Equal(0, stub1.Result);
            Dictionary <string, object> arguments = new Dictionary <string, object>();

            arguments["a"] = 1000;
            arguments["b"] = 100;
            arguments["c"] = 10;
            arguments["e"] = 1;
            eventBus.Notify("ITestEventHandler.Sum", arguments);
            Assert.Equal(1110, stub1.Result);
        }
Exemplo n.º 11
0
        public IServiceProvider CreateContainer(ShellSettings settings, ShellBlueprint blueprint)
        {
            var featureByType = blueprint.Dependencies.ToDictionary(x => x.Type, x => x.Feature);
            IServiceCollection tenantServiceCollection = _serviceProvider.CreateChildContainer(_applicationServices);

            tenantServiceCollection.AddInstance(settings);
            tenantServiceCollection.AddInstance(blueprint.Descriptor);
            tenantServiceCollection.AddInstance(blueprint);

            // Sure this is right?
            tenantServiceCollection.AddInstance(_loggerFactory);

            foreach (var dependency in blueprint.Dependencies
                     .Where(t => !typeof(IModule).IsAssignableFrom(t.Type)))
            {
                foreach (var interfaceType in dependency.Type.GetInterfaces()
                         .Where(itf => typeof(IDependency).IsAssignableFrom(itf)))
                {
                    _logger.LogDebug("Type: {0}, Interface Type: {1}", dependency.Type, interfaceType);

                    if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddSingleton(interfaceType, dependency.Type);
                    }
                    else if (typeof(IUnitOfWorkDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddScoped(interfaceType, dependency.Type);
                    }
                    else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddTransient(interfaceType, dependency.Type);
                    }
                    else
                    {
                        tenantServiceCollection.AddScoped(interfaceType, dependency.Type);
                    }
                }
            }

            // Configure event handlers, they are not part of the blueprint, so they have
            // to be added manually. Or need to create a module for this.
            tenantServiceCollection.AddScoped <IEventBus, DefaultOrchardEventBus>();
            tenantServiceCollection.AddSingleton <IEventBusState, EventBusState>();

            // Configuring data access
            var indexes = blueprint
                          .Dependencies
                          .Where(x => typeof(IIndexProvider).IsAssignableFrom(x.Type))
                          .Select(x => x.Type).ToArray();

            if (settings.DatabaseProvider != null)
            {
                var store = new Store(cfg =>
                {
                    // @"Data Source =.; Initial Catalog = test1; User Id=sa;Password=demo123!"

                    IConnectionFactory connectionFactory = null;

                    switch (settings.DatabaseProvider)
                    {
                    case "SqlConnection":
                        connectionFactory = new DbConnectionFactory <SqlConnection>(settings.ConnectionString);
                        break;

                    //case "SqliteConnection":
                    //    connectionFactory = new DbConnectionFactory<SqliteConnection>(settings.ConnectionString);
                    //    break;
                    default:
                        throw new ArgumentException("Unkown database provider: " + settings.DatabaseProvider);
                    }

                    var sqlFactory = new SqlDocumentStorageFactory(connectionFactory);;

                    cfg.ConnectionFactory      = connectionFactory;
                    cfg.DocumentStorageFactory = sqlFactory;
                    cfg.IsolationLevel         = sqlFactory.IsolationLevel = IsolationLevel.ReadUncommitted;

                    if (!String.IsNullOrWhiteSpace(settings.TablePrefix))
                    {
                        cfg.TablePrefix = sqlFactory.TablePrefix = settings.TablePrefix + "_";
                    }

                    //cfg.RunDefaultMigration();
                }
                                      );

                var idGenerator = new LinearBlockIdGenerator(store.Configuration.ConnectionFactory, 20, "contentitem", store.Configuration.TablePrefix);

                store.RegisterIndexes(indexes);

                tenantServiceCollection.AddInstance <IStore>(store);
                tenantServiceCollection.AddInstance <LinearBlockIdGenerator>(idGenerator);

                tenantServiceCollection.AddScoped <ISession>(serviceProvider =>
                                                             store.CreateSession()
                                                             );
            }

            tenantServiceCollection.AddInstance <ITypeFeatureProvider>(new TypeFeatureProvider(featureByType));

            IServiceCollection moduleServiceCollection =
                _serviceProvider.CreateChildContainer(_applicationServices);

            foreach (var dependency in blueprint.Dependencies
                     .Where(t => typeof(IModule).IsAssignableFrom(t.Type)))
            {
                moduleServiceCollection.AddScoped(typeof(IModule), dependency.Type);
            }

            var moduleServiceProvider = moduleServiceCollection.BuildServiceProvider();

            // Let any module add custom service descriptors to the tenant
            foreach (var service in moduleServiceProvider.GetServices <IModule>())
            {
                service.Configure(tenantServiceCollection);
            }

            // Register event handlers on the event bus
            var eventHandlers = tenantServiceCollection
                                .Select(x => x.ImplementationType)
                                .Where(t => t != null && typeof(IEventHandler).IsAssignableFrom(t) && t.GetTypeInfo().IsClass)
                                .ToArray();

            foreach (var handlerClass in eventHandlers)
            {
                tenantServiceCollection.AddScoped(handlerClass);

                // Register dynamic proxies to intercept direct calls if an IEventHandler is resolved, dispatching the call to
                // the event bus.

                foreach (var i in handlerClass.GetInterfaces().Where(t => typeof(IEventHandler).IsAssignableFrom(t)))
                {
                    tenantServiceCollection.AddScoped(i, serviceProvider =>
                    {
                        var proxy      = DefaultOrchardEventBus.CreateProxy(i);
                        proxy.EventBus = serviceProvider.GetService <IEventBus>();
                        return(proxy);
                    });
                }
            }

            var shellServiceProvider = tenantServiceCollection.BuildServiceProvider();
            var eventBusState        = shellServiceProvider.GetService <IEventBusState>();

            // Register any IEventHandler method in the event bus
            foreach (var handlerClass in eventHandlers)
            {
                foreach (var handlerInterface in handlerClass.GetInterfaces().Where(x => typeof(IEventHandler).IsAssignableFrom(x)))
                {
                    foreach (var interfaceMethod in handlerInterface.GetMethods())
                    {
                        //var classMethod = handlerClass.GetMethods().Where(x => x.Name == interfaceMethod.Name && x.GetParameters().Length == interfaceMethod.GetParameters().Length).FirstOrDefault();
                        Func <IServiceProvider, IDictionary <string, object>, Task> d = (sp, parameters) => DefaultOrchardEventBus.Invoke(sp, parameters, interfaceMethod, handlerClass);
                        eventBusState.Add(handlerInterface.Name + "." + interfaceMethod.Name, d);
                    }
                }
            }

            return(shellServiceProvider);
        }
Exemplo n.º 12
0
        public IServiceProvider CreateContainer(ShellSettings settings, ShellBlueprint blueprint)
        {
            IServiceCollection tenantServiceCollection = _serviceProvider.CreateChildContainer(_applicationServices);

            tenantServiceCollection.AddSingleton(settings);
            tenantServiceCollection.AddSingleton(blueprint.Descriptor);
            tenantServiceCollection.AddSingleton(blueprint);

            AddCoreServices(tenantServiceCollection);

            // Configure event handlers, they are not part of the blueprint, so they have
            // to be added manually. Or need to create a module for this.
            tenantServiceCollection.AddScoped <IEventBus, DefaultOrchardEventBus>();
            tenantServiceCollection.AddSingleton <IEventBusState, EventBusState>();

            // Execute IStartup registrations

            // TODO: Use StartupLoader in RTM and then don't need to register the classes anymore then

            IServiceCollection moduleServiceCollection = _serviceProvider.CreateChildContainer(_applicationServices);

            foreach (var dependency in blueprint.Dependencies.Where(t => typeof(Microsoft.AspNetCore.Modules.IStartup).IsAssignableFrom(t.Key)))
            {
                moduleServiceCollection.AddSingleton(typeof(Microsoft.AspNetCore.Modules.IStartup), dependency.Key);
                tenantServiceCollection.AddSingleton(typeof(Microsoft.AspNetCore.Modules.IStartup), dependency.Key);
            }

            // Add a default configuration if none has been provided
            var configuration = new ConfigurationBuilder().AddInMemoryCollection().Build();

            moduleServiceCollection.TryAddSingleton(configuration);
            tenantServiceCollection.TryAddSingleton(configuration);

            // Make shell settings available to the modules
            moduleServiceCollection.AddSingleton(settings);

            var moduleServiceProvider = moduleServiceCollection.BuildServiceProvider();

            // Index all service descriptors by their feature id
            var featureServiceCollections = new Dictionary <IFeatureInfo, ServiceCollection>();

            // Let any module add custom service descriptors to the tenant
            foreach (var startup in moduleServiceProvider.GetServices <Microsoft.AspNetCore.Modules.IStartup>())
            {
                var feature = blueprint.Dependencies.FirstOrDefault(x => x.Key == startup.GetType()).Value.FeatureInfo;

                ServiceCollection featureServiceCollection;
                ServiceCollection startupServices = new ServiceCollection();

                if (!featureServiceCollections.TryGetValue(feature, out featureServiceCollection))
                {
                    featureServiceCollections.Add(feature, featureServiceCollection = new ServiceCollection());
                }

                startup.ConfigureServices(startupServices);
                tenantServiceCollection.Add(startupServices);
                featureServiceCollection.Add(startupServices);
            }

            (moduleServiceProvider as IDisposable).Dispose();

            // add already instanciated services like DefaultOrchardHost
            var applicationServiceDescriptors = _applicationServices.Where(x => x.Lifetime == ServiceLifetime.Singleton);

            // Register event handlers on the event bus
            var eventHandlers = tenantServiceCollection
                                .Union(applicationServiceDescriptors)
                                .Select(x => x.ImplementationType)
                                .Distinct()
                                .Where(t => t != null && typeof(IEventHandler).IsAssignableFrom(t) && t.GetTypeInfo().IsClass)
                                .ToArray();

            foreach (var handlerClass in eventHandlers)
            {
                // Register dynamic proxies to intercept direct calls if an IEventHandler is resolved, dispatching the call to
                // the event bus.

                foreach (var i in handlerClass.GetInterfaces().Where(t => t != typeof(IEventHandler) && typeof(IEventHandler).IsAssignableFrom(t)))
                {
                    tenantServiceCollection.AddScoped(i, serviceProvider =>
                    {
                        var proxy      = DefaultOrchardEventBus.CreateProxy(i);
                        proxy.EventBus = serviceProvider.GetService <IEventBus>();
                        return(proxy);
                    });
                }
            }

            var shellServiceProvider = tenantServiceCollection.BuildServiceProvider();

            using (var scope = shellServiceProvider.CreateScope())
            {
                var eventBusState = scope.ServiceProvider.GetService <IEventBusState>();

                // Register any IEventHandler method in the event bus
                foreach (var handlerClass in eventHandlers)
                {
                    foreach (var handlerInterface in handlerClass.GetInterfaces().Where(x => typeof(IEventHandler).IsAssignableFrom(x) && typeof(IEventHandler) != x))
                    {
                        foreach (var interfaceMethod in handlerInterface.GetMethods())
                        {
                            if (_logger.IsEnabled(LogLevel.Debug))
                            {
                                _logger.LogDebug($"{handlerClass.Name}/{handlerInterface.Name}.{interfaceMethod.Name}");
                            }

                            //var classMethod = handlerClass.GetMethods().Where(x => x.Name == interfaceMethod.Name && x.GetParameters().Length == interfaceMethod.GetParameters().Length).FirstOrDefault();
                            Func <IServiceProvider, IDictionary <string, object>, Task> d = (sp, parameters) => DefaultOrchardEventBus.Invoke(sp, parameters, interfaceMethod, handlerClass);
                            var messageName = $"{handlerInterface.Name}.{interfaceMethod.Name}";
                            var className   = handlerClass.FullName;
                            eventBusState.Add(messageName, d);
                        }
                    }
                }
            }

            // Register all DIed types in ITypeFeatureProvider
            var typeFeatureProvider = shellServiceProvider.GetRequiredService <ITypeFeatureProvider>();

            foreach (var featureServiceCollection in featureServiceCollections)
            {
                foreach (var serviceDescriptor in featureServiceCollection.Value)
                {
                    if (serviceDescriptor.ImplementationType != null)
                    {
                        typeFeatureProvider.TryAdd(serviceDescriptor.ImplementationType, featureServiceCollection.Key);
                    }
                    else if (serviceDescriptor.ImplementationInstance != null)
                    {
                        typeFeatureProvider.TryAdd(serviceDescriptor.ImplementationInstance.GetType(), featureServiceCollection.Key);
                    }
                    else
                    {
                        // Factory, we can't know which type will be returned
                    }
                }
            }

            return(shellServiceProvider);
        }
Exemplo n.º 13
0
        public IServiceProvider CreateContainer(ShellSettings settings, ShellBlueprint blueprint)
        {
            IServiceCollection tenantServiceCollection = _serviceProvider.CreateChildContainer(_applicationServices);

            tenantServiceCollection.AddSingleton(settings);
            tenantServiceCollection.AddSingleton(blueprint.Descriptor);
            tenantServiceCollection.AddSingleton(blueprint);

            AddCoreServices(tenantServiceCollection);

            // Sure this is right?
            tenantServiceCollection.AddSingleton(_loggerFactory);

            foreach (var dependency in blueprint.Dependencies)
            {
                foreach (var interfaceType in dependency.Type.GetInterfaces())
                {
                    // GetInterfaces returns the full hierarchy of interfaces
                    if (interfaceType == typeof(ISingletonDependency) ||
                        interfaceType == typeof(ITransientDependency) ||
                        interfaceType == typeof(IDependency) ||
                        !typeof(IDependency).IsAssignableFrom(interfaceType))
                    {
                        continue;
                    }

                    if (_logger.IsEnabled(LogLevel.Debug))
                    {
                        _logger.LogDebug("Type: {0}, Interface Type: {1}", dependency.Type, interfaceType);
                    }

                    if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddSingleton(interfaceType, dependency.Type);
                    }
                    else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddTransient(interfaceType, dependency.Type);
                    }
                    else if (typeof(IDependency).IsAssignableFrom(interfaceType))
                    {
                        tenantServiceCollection.AddScoped(interfaceType, dependency.Type);
                    }
                }
            }

            // Register components
            foreach (var dependency in blueprint.Dependencies)
            {
                var serviceComponentAttribute = dependency.Type.GetTypeInfo().GetCustomAttribute <ServiceScopeAttribute>();
                if (serviceComponentAttribute != null)
                {
                    if (_logger.IsEnabled(LogLevel.Debug))
                    {
                        _logger.LogDebug("Type: {0}, Interface Type: {1}", dependency.Type, serviceComponentAttribute.ServiceType);
                    }

                    serviceComponentAttribute.Register(tenantServiceCollection, dependency.Type);
                }
            }

            // Configure event handlers, they are not part of the blueprint, so they have
            // to be added manually. Or need to create a module for this.
            tenantServiceCollection.AddScoped <IEventBus, DefaultOrchardEventBus>();
            tenantServiceCollection.AddSingleton <IEventBusState, EventBusState>();

            //// Apply custom options for the tenant
            //var options = blueprint
            //.Dependencies
            //.Where(x => typeof(IConfigure).IsAssignableFrom(x.Type))
            //.Select(x => x.Type).ToArray();

            //// TODO: Group all options by type and reuse the same configuration object
            //// such that multiple feature can update the same configuration object.

            //foreach (var type in options)
            //{
            //    var optionType = type
            //        .GetInterfaces()
            //        .Where(x => typeof(IConfigure).IsAssignableFrom(x))
            //        .FirstOrDefault()
            //        .GetGenericArguments()
            //        .FirstOrDefault();

            //    if(optionType == null)
            //    {
            //        // Ignore non-generic implementation
            //        continue;
            //    }

            //    var optionObject = Activator.CreateInstance(optionType);
            //    var configureMethod = type.GetMethod("Configure");
            //    var optionHost = Activator.CreateInstance(type);
            //    configureMethod.Invoke(optionHost, new[] { optionObject });
            //    tenantServiceCollection.ConfigureOptions(optionObject);
            //}

            // Execute IStartup registrations

            // TODO: Use StartupLoader in RTM and then don't need to register the classes anymore then

            IServiceCollection moduleServiceCollection = _serviceProvider.CreateChildContainer(_applicationServices);

            foreach (var dependency in blueprint.Dependencies.Where(t => typeof(IStartup).IsAssignableFrom(t.Type)))
            {
                moduleServiceCollection.AddSingleton(typeof(IStartup), dependency.Type);
                tenantServiceCollection.AddSingleton(typeof(IStartup), dependency.Type);
            }

            // Make shell settings available to the modules
            moduleServiceCollection.AddSingleton(settings);

            var moduleServiceProvider = moduleServiceCollection.BuildServiceProvider();

            // Let any module add custom service descriptors to the tenant
            foreach (var service in moduleServiceProvider.GetServices <IStartup>())
            {
                service.ConfigureServices(tenantServiceCollection);
            }

            // Configuring data access

            var indexes = tenantServiceCollection
                          .Select(x => x.ImplementationType)
                          .Where(t => t != null && typeof(IIndexProvider).IsAssignableFrom(t) && t.GetTypeInfo().IsClass)
                          .Distinct()
                          .ToArray();

            if (settings.DatabaseProvider != null)
            {
                var store = new Store(cfg =>
                {
                    IConnectionFactory connectionFactory = null;

                    switch (settings.DatabaseProvider)
                    {
                    case "SqlConnection":
                        connectionFactory = new DbConnectionFactory <SqlConnection>(settings.ConnectionString);
                        break;

                    case "SqliteConnection":
                        connectionFactory = new DbConnectionFactory <SqliteConnection>(settings.ConnectionString);
                        break;

                    default:
                        throw new ArgumentException("Unknown database provider: " + settings.DatabaseProvider);
                    }

                    cfg.ConnectionFactory = connectionFactory;
                    cfg.IsolationLevel    = IsolationLevel.ReadUncommitted;

                    if (!String.IsNullOrWhiteSpace(settings.TablePrefix))
                    {
                        cfg.TablePrefix = settings.TablePrefix + "_";
                    }
#if SQL
                    var sqlFactory               = new SqlDocumentStorageFactory(connectionFactory);
                    sqlFactory.IsolationLevel    = IsolationLevel.ReadUncommitted;
                    sqlFactory.ConnectionFactory = connectionFactory;
                    if (!String.IsNullOrWhiteSpace(settings.TablePrefix))
                    {
                        sqlFactory.TablePrefix = settings.TablePrefix + "_";
                    }
                    cfg.DocumentStorageFactory = sqlFactory;
#else
                    var storageFactory         = new LightningDocumentStorageFactory(Path.Combine(_appDataFolderRoot.RootFolder, "Sites", settings.Name, "Documents"));
                    cfg.DocumentStorageFactory = storageFactory;
#endif


                    //cfg.RunDefaultMigration();
                }
                                      );

                var idGenerator = new LinearBlockIdGenerator(store.Configuration.ConnectionFactory, 20, "contentitem", store.Configuration.TablePrefix);

                store.RegisterIndexes(indexes);

                tenantServiceCollection.AddSingleton <IStore>(store);
                tenantServiceCollection.AddSingleton <LinearBlockIdGenerator>(idGenerator);

                tenantServiceCollection.AddScoped <ISession>(serviceProvider => store.CreateSession());
            }

            // Register event handlers on the event bus
            var eventHandlers = tenantServiceCollection
                                .Select(x => x.ImplementationType)
                                .Distinct()
                                .Where(t => t != null && typeof(IEventHandler).IsAssignableFrom(t) && t.GetTypeInfo().IsClass)
                                .ToArray();

            foreach (var handlerClass in eventHandlers)
            {
                tenantServiceCollection.AddScoped(handlerClass);

                // Register dynamic proxies to intercept direct calls if an IEventHandler is resolved, dispatching the call to
                // the event bus.

                foreach (var i in handlerClass.GetInterfaces().Where(t => typeof(IEventHandler).IsAssignableFrom(t)))
                {
                    tenantServiceCollection.AddScoped(i, serviceProvider =>
                    {
                        var proxy      = DefaultOrchardEventBus.CreateProxy(i);
                        proxy.EventBus = serviceProvider.GetService <IEventBus>();
                        return(proxy);
                    });
                }
            }

            var shellServiceProvider = tenantServiceCollection.BuildServiceProvider();
            var eventBusState        = shellServiceProvider.GetService <IEventBusState>();

            // Register any IEventHandler method in the event bus
            foreach (var handlerClass in eventHandlers)
            {
                foreach (var handlerInterface in handlerClass.GetInterfaces().Where(x => typeof(IEventHandler).IsAssignableFrom(x) && typeof(IEventHandler) != x))
                {
                    foreach (var interfaceMethod in handlerInterface.GetMethods())
                    {
                        if (_logger.IsEnabled(LogLevel.Debug))
                        {
                            _logger.LogDebug($"{handlerClass.Name}/{handlerInterface.Name}.{interfaceMethod.Name}");
                        }

                        //var classMethod = handlerClass.GetMethods().Where(x => x.Name == interfaceMethod.Name && x.GetParameters().Length == interfaceMethod.GetParameters().Length).FirstOrDefault();
                        Func <IServiceProvider, IDictionary <string, object>, Task> d = (sp, parameters) => DefaultOrchardEventBus.Invoke(sp, parameters, interfaceMethod, handlerClass);
                        eventBusState.Add(handlerInterface.Name + "." + interfaceMethod.Name, d);
                    }
                }
            }

            return(shellServiceProvider);
        }