/// <summary>
        /// Configures the <paramref name="application"/> to use the specified existing <paramref name="serviceProvider"/>.
        /// </summary>
        /// <remarks>Use this method to activate IoC from an existing <see cref="IServiceProvider"/> implementation.</remarks>
        /// <typeparam name="TApplication">Type of the <see cref="HttpApplication"/> which the <see cref="IServiceProvider"/>
        /// will be use to retrieve the services using IoC.</typeparam>
        /// <param name="application">The <see cref="HttpApplication"/> which the <see cref="IServiceProvider"/> will be used on.</param>
        /// <param name="serviceProvider">Existing <see cref="IServiceProvider"/> which contains the services.</param>
        /// <returns>The <paramref name="application"/> instance to continue the configuration of it.</returns>
        /// <exception cref="ArgumentNullException">If the <paramref name="application"/> argument is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentNullException">If the <paramref name="serviceProvider"/> argument is <see langword="null"/>.</exception>
        public static TApplication UseServiceProvider <TApplication>(this TApplication application, IServiceProvider serviceProvider)
            where TApplication : HttpApplication
        {
            Check.IsNotNull(application, nameof(application));
            Check.IsNotNull(serviceProvider, nameof(serviceProvider));

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceProvider, HttpRuntime.WebObjectActivator);

            HostingEnvironment.RegisterObject(serviceProviderAdapter);

            HttpRuntime.WebObjectActivator = serviceProviderAdapter;

            return(application);
        }
        public void GetService_UsingServiceCollection_NotInServiceCollectionAndNotInTheNextProvider()
        {
            var serviceCollection = new ServiceCollection();

            var nextServiceProvider = new Mock <IServiceProvider>(MockBehavior.Strict);

            nextServiceProvider.Setup(sp => sp.GetService(typeof(DependentService)))
            .Returns(null);

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceCollection, nextServiceProvider.Object);

            var result = serviceProviderAdapter.GetService(typeof(DependentService)).As <DependentService>();

            result.Should().NotBeNull();
        }
        /// <summary>
        /// Add an existing <see cref="IServiceCollection"/> which will define as a <see cref="IServiceProvider"/>
        /// for the <see cref="HttpRuntime.WebObjectActivator"/> provider services of the <typeparamref name="TApplication"/>.
        /// </summary>
        /// <typeparam name="TApplication">Type of the <see cref="HttpApplication"/> which the <see cref="IServiceProvider"/>
        /// will be create from a <see cref="IServiceCollection"/>.</typeparam>
        /// <param name="application">The <see cref="HttpApplication"/> which the <see cref="IServiceCollection"/> will be registered on.</param>
        /// <param name="serviceCollection">Existing <see cref="IServiceCollection"/> which contains the registered services.</param>
        /// <returns>A new <see cref="IServiceCollection"/> which allows to defines the services to provide.</returns>
        /// <exception cref="ArgumentNullException">If the <paramref name="application"/> argument is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentNullException">If the <paramref name="serviceCollection"/> argument is <see langword="null"/>.</exception>
        public static IServiceCollection AddServiceCollection <TApplication>(this TApplication application, IServiceCollection serviceCollection)
            where TApplication : HttpApplication
        {
            Check.IsNotNull(application, nameof(application));
            Check.IsNotNull(serviceCollection, nameof(serviceCollection));

            AddDefaultAspNetServices(serviceCollection, application);

            var serviceProvider = new ServiceProviderAdapter(serviceCollection, HttpRuntime.WebObjectActivator);

            HostingEnvironment.RegisterObject(serviceProvider);

            HttpRuntime.WebObjectActivator = serviceProvider;

            return(serviceCollection);
        }
        public void GetService_UsingServiceCollection_NotInServiceCollectionUsingNextProvider()
        {
            var serviceCollection = new ServiceCollection();

            var service = new Service(null);

            var nextServiceProvider = new Mock <IServiceProvider>(MockBehavior.Strict);

            nextServiceProvider.Setup(sp => sp.GetService(typeof(IService)))
            .Returns(service);

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceCollection, nextServiceProvider.Object);

            var result = serviceProviderAdapter.GetService(typeof(IService)).As <Service>();

            result.Should().BeSameAs(service);
        }
        public void GetService_UsingServiceCollection_WithInstantiationInternalClass()
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton <IDependentService, DependentService>();

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceCollection, null);

            var result = serviceProviderAdapter.GetService(typeof(ServiceInternal)).As <ServiceInternal>();

            result.Should().NotBeNull();

            // Calls again to check the internal cache have not problem
            var result2 = serviceProviderAdapter.GetService(typeof(ServiceInternal)).As <ServiceInternal>();

            result2.Should().NotBeNull();
        }
        public void Should_Be_Able_To_Resolve_Logger()
        {
            /* Setup */
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddZyRabbit();
            using var provider = serviceCollection.BuildServiceProvider();
            var providerAdapter = new ServiceProviderAdapter(provider);

            /* Test */
            var logger1 = providerAdapter.GetService <ILogger <IExclusiveLock> >();
            var logger2 = providerAdapter.GetService <ILogger <IExclusiveLock> >();

            /* Assert */
            Assert.Same(logger1, logger2);
            Assert.NotNull(logger1);
        }
        public void GetService_UsingServiceProvider_InServiceCollectionWithInjection()
        {
            var service1 = Mock.Of <IService>();
            var service2 = Mock.Of <IService>();

            var serviceProvider = new Mock <IServiceProvider>(MockBehavior.Strict);

            serviceProvider.SetupSequence(sp => sp.GetService(typeof(IService)))
            .Returns(service1)
            .Returns(service2);

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceProvider.Object, null);

            serviceProviderAdapter.GetService(typeof(IService)).Should().BeSameAs(service1);

            // Calls again to check the internal cache have not problem
            serviceProviderAdapter.GetService(typeof(IService)).Should().BeSameAs(service2);
        }
        public void GetService_UsingServiceCollection_WithInstantiationAspDotNetControlWithInjectionWithNotAspNamespace()
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton <IDependentService, DependentService>();

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceCollection, null);

            var result = serviceProviderAdapter.GetService(typeof(ControlWithService)).As <ControlWithService>();

            result.Should().NotBeNull();
            result.DependentService.Should().NotBeNull();

            // Calls again to check the internal cache have not problem
            var result2 = serviceProviderAdapter.GetService(typeof(Service)).As <Service>();

            result2.Should().NotBeNull();
            result2.DependentService.Should().NotBeNull();
        }
        public void Should_Be_Able_To_Resolve_Client_With_Plugins_From_ServiceCollection()
        {
            /* Setup */
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddZyRabbit(new ZyRabbitOptions
            {
                Plugins = p => p.UseStateMachine()
            });
            using var provider = serviceCollection.BuildServiceProvider();
            var providerAdapter = new ServiceProviderAdapter(provider);

            /* Test */
            var client     = providerAdapter.GetService <IBusClient>();
            var middleware = providerAdapter.GetService <RetrieveStateMachineMiddleware>();

            /* Assert */
            Assert.NotNull(client);
            Assert.NotNull(middleware);
        }
        public async Task Should_Be_Able_To_Publish_Message_From_Resolved_Client()
        {
            /* Setup */
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddZyRabbit();
            using var provider = serviceCollection.BuildServiceProvider();
            var providerAdapter = new ServiceProviderAdapter(provider);

            /* Test */
            var client = providerAdapter.GetService <IBusClient>();
            await client.PublishAsync(new BasicMessage());

            await client.DeleteExchangeAsync <BasicMessage>();

            var disposer = providerAdapter.GetService <IResourceDisposer>();

            /* Assert */
            disposer.Dispose();
        }
        public async Task Should_Honor_Client_Config_From_Options()
        {
            /* Setup */
            var serviceCollection = new ServiceCollection();
            var config            = ZyRabbitConfiguration.Local;

            config.VirtualHost = "/foo";
            serviceCollection.AddZyRabbit(new ZyRabbitOptions
            {
                ClientConfiguration = config
            });

            /* Test */
            await Assert.ThrowsAnyAsync <BrokerUnreachableException>(async() =>
            {
                using var provider  = serviceCollection.BuildServiceProvider();
                var providerAdapter = new ServiceProviderAdapter(provider);
                var client          = providerAdapter.GetService <IBusClient>();
                await client.CreateChannelAsync();
            });
        }
        public void Stop_UsingServiceCollection()
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton <IDependentService, DependentService>();

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceCollection, null);

            var result = serviceProviderAdapter.GetService(typeof(IDependentService)).As <DependentService>();

            result.Should().NotBeNull();
            result.DisposeCalled.Should().BeFalse();

            // Stop() the adapter, it is mean we dispose the provider
            serviceProviderAdapter.Stop(true);

            result.DisposeCalled.Should().BeTrue();

            // Check the ObjectDisposedException if calling the GetService() method
            serviceProviderAdapter.Invoking(spa => spa.GetService(typeof(IDependentService))).Should().ThrowExactly <ObjectDisposedException>()
            .And.ObjectName.Should().Be("PosInformatique.AspNet.WebForms.DependencyInjection.ServiceProviderAdapter");
        }
        public void Stop_UsingServiceProvider()
        {
            var dependentService = Mock.Of <IDependentService>();

            var serviceProvider = new Mock <IServiceProvider>(MockBehavior.Strict);

            serviceProvider.As <IDisposable>();
            serviceProvider.Setup(sp => sp.GetService(typeof(IDependentService)))
            .Returns(dependentService);

            var serviceProviderAdapter = new ServiceProviderAdapter(serviceProvider.Object, null);

            serviceProviderAdapter.GetService(typeof(IDependentService)).As <DependentService>();

            // Stop() the adapter, it is mean we dispose the provider BUT the no
            serviceProviderAdapter.Stop(true);

            // Verify the Dispose() method is not called for a IServiceProvider which implement the IDisposable interface
            serviceProvider.As <IDisposable>().Verify(sp => sp.Dispose(), Times.Never);

            // Check the ObjectDisposedException if calling the GetService() method
            serviceProviderAdapter.Invoking(spa => spa.GetService(typeof(IDependentService))).Should().ThrowExactly <ObjectDisposedException>()
            .And.ObjectName.Should().Be("PosInformatique.AspNet.WebForms.DependencyInjection.ServiceProviderAdapter");
        }
        public async Task Should_Be_Able_To_Resolve_Middleware_With_Parameter()
        {
            /* Setup */
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddZyRabbit();
            using var provider = serviceCollection.BuildServiceProvider();
            var providerAdapter = new ServiceProviderAdapter(provider);

            // Configure middleware via options to throw the InvalidOperationException exception
            var options = new ExchangeDeclareOptions
            {
                ThrowOnFailFunc = _ => true
            };

            /* Test */
            var middleware = providerAdapter.GetService <ExchangeDeclareMiddleware>(options);

            /* Assert */
            await Assert.ThrowsAnyAsync <InvalidOperationException>(async() =>
            {
                await middleware.InvokeAsync(null, CancellationToken.None);
            });
        }