/// <summary>
        /// Creates a framework initialiser from discovered modules provided by a dependency context.
        /// </summary>
        /// <param name="context">The dependency context.</param>
        /// <param name="configuration">The framework configuration.</param>
        /// <returns>The framework initialiser.</returns>
        public static FrameworkInitialiser FromDependencyContext(DependencyContext context, IConfiguration configuration)
        {
            var assemblyProvider = new DependencyContextAssemblyProvider(context);

            var init = new FrameworkInitialiser(configuration);

            init._partManager = new PartManager();
            init._partManager.PartFeatureProviders.Add(new ModulePartFeatureProvider());

            foreach (var assembly in assemblyProvider.Assemblies)
            {
                init._partManager.Parts.Add(new AssemblyPart(assembly));
            }

            var feature = new ModulePartFeature();

            init._partManager.PopulateFeature(feature);

            init._moduleProvider = new ModuleProvider(
                feature.ModuleTypes.Select(t => (IModule)Activator.CreateInstance(t)));

            init._featureProvider      = CreateFeatureProvider(init._moduleProvider);
            init._featureStateProvider = new FeatureStateProvider(init._featureProvider, init._configuration);

            return(init);
        }
        public void FromModules_ValidatesArguments()
        {
            // Arrange

            // Act

            // Assert
            Assert.Throws <ArgumentNullException>(() => FrameworkInitialiser.FromModules(null /* modules */, null /* configuration */));
            Assert.Throws <ArgumentNullException>(() => FrameworkInitialiser.FromModules(Array.Empty <IModule>(), null /* configuration */));
        }
        public void FromModules_CreatesFeatureStateProvider()
        {
            // Arrange
            var module        = new TestModule();
            var configuration = new ConfigurationBuilder().Build();

            // Act
            var init = FrameworkInitialiser.FromModules(new IModule[] { module }, configuration);

            // Assert
            Assert.NotNull(init);
            Assert.NotNull(init.FeatureStateProvider);
        }
        public void FromDependencyContext_CreatesFeatureStateProvider()
        {
            // Arrange
            var dependencyContext = DependencyContext.Default;
            var configuration     = new ConfigurationBuilder().Build();

            // Act
            var init = FrameworkInitialiser.FromDependencyContext(dependencyContext, configuration);

            // Assert
            Assert.NotNull(init);
            Assert.NotNull(init.FeatureStateProvider);
        }
        public void AddServices_AddsFeatureStateProvider()
        {
            // Arrange
            var module        = new TestModule();
            var configuration = new ConfigurationBuilder().Build();
            var init          = FrameworkInitialiser.FromModules(new IModule[] { module }, configuration);
            var services      = new ServiceCollection();

            // Act
            init.AddServices(services);

            // Assert
            Assert.Contains(services, sd => sd.ServiceType == typeof(IFeatureStateProvider) && sd.Lifetime == ServiceLifetime.Singleton);
        }
        public void AddServices_AddsServicesFromFeatures()
        {
            // Arrange
            var module        = new TestModule();
            var configuration = new ConfigurationBuilder().Build();
            var init          = FrameworkInitialiser.FromModules(new IModule[] { module }, configuration);
            var services      = new ServiceCollection();

            // Act
            init.AddServices(services);

            // Assert
            Assert.Contains(services, sd => sd.ServiceType == typeof(FeatureService));
        }
        public void FromModules_CreatesPartManager()
        {
            // Arrange
            var module        = new TestModule();
            var configuration = new ConfigurationBuilder().Build();

            // Act
            var init = FrameworkInitialiser.FromModules(new IModule[] { module }, configuration);

            // Assert
            Assert.NotNull(init);
            Assert.NotNull(init.PartManager);
            Assert.Contains(init.PartManager.PartFeatureProviders, pfp => pfp is ModulePartFeatureProvider);
            Assert.Contains(init.PartManager.Parts, p => p is AssemblyPart && ((AssemblyPart)p).Assembly == typeof(TestModule).Assembly);
        }
        public void ExtendConfiguration_AddsFeatureConfiguration()
        {
            // Arrange
            var module        = new TestModule();
            var configuration = new ConfigurationBuilder().Build();
            var init          = FrameworkInitialiser.FromModules(new IModule[] { module }, configuration);
            var builder       = new ConfigurationBuilder();
            var context       = new WebHostBuilderContext();

            // Act
            init.ExtendConfiguration(context, builder);

            // Assert
            Assert.Contains(builder.Sources, cs => cs is FeatureConfigurationSource);
        }
        public void FromDependencyContext_CreatesPartManager()
        {
            // Arrange
            var dependencyContext = DependencyContext.Default;
            var configuration     = new ConfigurationBuilder().Build();

            // Act
            var init = FrameworkInitialiser.FromDependencyContext(dependencyContext, configuration);

            // Assert
            Assert.NotNull(init);
            Assert.NotNull(init.PartManager);
            Assert.Contains(init.PartManager.PartFeatureProviders, pfp => pfp is ModulePartFeatureProvider);
            Assert.Contains(init.PartManager.Parts, p => p is AssemblyPart && ((AssemblyPart)p).Assembly == typeof(TestModule).Assembly);
        }
        /// <summary>
        /// Creates a framework initialiser from a fixed set of modules.
        /// </summary>
        /// <param name="modules">The set of modules.</param>
        /// <param name="configuration">The framework configuration.</param>
        /// <returns>The framework initialiser.</returns>
        public static FrameworkInitialiser FromModules(IModule[] modules, IConfiguration configuration)
        {
            Ensure.IsNotNull(modules, nameof(modules));

            var init = new FrameworkInitialiser(configuration);

            init._moduleProvider = new ModuleProvider(modules);
            init._partManager    = new PartManager();
            init._partManager.PartFeatureProviders.Add(new ModulePartFeatureProvider());

            foreach (var assembly in init._moduleProvider.Modules.Select(m => m.GetType().Assembly))
            {
                init._partManager.Parts.Add(new AssemblyPart(assembly));
            }

            init._featureProvider      = CreateFeatureProvider(init._moduleProvider);
            init._featureStateProvider = new FeatureStateProvider(init._featureProvider, init._configuration);

            return(init);
        }