public static IEnumerable<object[]> TestServiceDescriptors(ServiceLifetime lifetime)
        {
            Func<object, object, bool> compare;

            if (lifetime == ServiceLifetime.Transient)
            {
                // Expect service references to be different for transient descriptors
                compare = (service1, service2) => service1 != service2;
            }
            else
            {
                // Expect service references to be the same for singleton and scoped descriptors
                compare = (service1, service2) => service1 == service2;
            }

            // Implementation Type Descriptor
            yield return new object[]
            {
                new[] { new ServiceDescriptor(typeof(IFakeService), typeof(FakeService), lifetime) },
                typeof(IFakeService),
                compare,
            };
            // Closed Generic Descriptor
            yield return new object[]
            {
                new[] { new ServiceDescriptor(typeof(IFakeOpenGenericService<string>), typeof(FakeService), lifetime) },
                typeof(IFakeOpenGenericService<string>),
                compare,
            };
            // Open Generic Descriptor
            yield return new object[]
            {
                new[]
                {
                    new ServiceDescriptor(typeof(IFakeService), typeof(FakeService), lifetime),
                    new ServiceDescriptor(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>), lifetime),
                },
                typeof(IFakeOpenGenericService<IFakeService>),
                compare,
            };
            // Factory Descriptor
            yield return new object[]
            {
                new[] { new ServiceDescriptor(typeof(IFakeService), _ => new FakeService(), lifetime) },
                typeof(IFakeService),
                compare,
            };

            if (lifetime == ServiceLifetime.Singleton)
            {
                // Instance Descriptor
                yield return new object[]
                {
                   new[] { new ServiceDescriptor(typeof(IFakeService), new FakeService()) },
                   typeof(IFakeService),
                   compare,
                };
            }
        }
            public static void RegistersExpectedServices(Type serviceType, Type implementationType, ServiceLifetime lifecycle)
            {
                var services = ApplicationInsightsExtensionsTests.GetServiceCollectionWithContextAccessor();

                services.AddApplicationInsightsTelemetry(new ConfigurationBuilder().Build());

                ServiceDescriptor service = services.Single(s => s.ServiceType == serviceType && s.ImplementationType == implementationType);
                Assert.Equal(lifecycle, service.Lifetime);
            }
        private static LifetimeManager GetLifetimeManager(ServiceLifetime lifecycle)
        {
            switch (lifecycle)
            {
                case ServiceLifetime.Transient:
                    return new TransientLifetimeManager();
                case ServiceLifetime.Singleton:
                    return new ContainerControlledLifetimeManager();
                case ServiceLifetime.Scoped:
                    return new HierarchicalLifetimeManager();
            }

            return new TransientLifetimeManager();
        }
 public static GenericFamilyExpression LifecycleIs(this GenericFamilyExpression instance, ServiceLifetime lifetime)
 {
     switch (lifetime)
     {
         case ServiceLifetime.Singleton:
             return instance.LifecycleIs(Lifecycles.Singleton);
         case ServiceLifetime.Scoped:
             return instance.LifecycleIs(Lifecycles.Container);
         case ServiceLifetime.Transient:
             return instance.LifecycleIs(Lifecycles.Unique);
         default:
             throw new ArgumentOutOfRangeException(nameof(lifetime), lifetime, null);
     }
 }
        public void AddWithTypeAddsServiceWithRightLifecyle(Action<IServiceCollection> addTypeAction,
                                                            Type expectedServiceType,
                                                            Type expectedImplementationType,
                                                            ServiceLifetime lifeCycle)
        {
            // Arrange
            var collection = new ServiceCollection();

            // Act
            addTypeAction(collection);

            // Assert
            var descriptor = Assert.Single(collection);
            Assert.Equal(expectedServiceType, descriptor.ServiceType);
            Assert.Equal(expectedImplementationType, descriptor.ImplementationType);
            Assert.Equal(lifeCycle, descriptor.Lifetime);
        }
Ejemplo n.º 6
0
 public static IServiceCollection AddValidationPipeline(this IServiceCollection services,
                                                        ServiceLifetime withLifetime = ServiceLifetime.Transient)
 {
     return(services.Add(typeof(IRequestPreProcessor <>), typeof(ValidationPipeline <>), withLifetime));
 }
 protected DependencyAttribute(ServiceLifetime dependencyType)
 {
     DependencyType = dependencyType;
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Adds the DbContext and the default services needed to run
 /// Piranha over Entity Framework Core.
 /// </summary>
 /// <param name="services">The current service collection</param>
 /// <param name="dboptions">The DbContext options builder</param>
 /// <param name="scope">The optional lifetime</param>
 /// <returns>The updated service collection</returns>
 public static IServiceCollection AddPiranhaEF(this IServiceCollection services,
                                               Action <DbContextOptionsBuilder> dboptions,
                                               ServiceLifetime scope = ServiceLifetime.Scoped)
 {
     return(AddPiranhaEF <Db>(services, dboptions, scope));
 }
        public void AddWithFactoryAddsServiceWithRightLifecyle(Action<IServiceCollection> addAction,
                                                               ServiceLifetime lifeCycle)
        {
            // Arrange
            var collection = new ServiceCollection();

            // Act
            addAction(collection);

            // Assert
            var descriptor = Assert.Single(collection);
            Assert.Equal(typeof(IFakeService), descriptor.ServiceType);
            Assert.Same(_factory, descriptor.ImplementationFactory);
            Assert.Equal(lifeCycle, descriptor.Lifetime);
        }
 public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action <IMapperConfigurationExpression> configAction, IEnumerable <Assembly> assemblies, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
 => AddAutoMapperClasses(services, (sp, cfg) => configAction?.Invoke(cfg), assemblies, serviceLifetime);
Ejemplo n.º 11
0
        /// <summary>
        /// Add a MySql-backed DbContext and MySQL health contributor to the Service Collection
        /// </summary>
        /// <typeparam name="TContext">Type of DbContext to add</typeparam>
        /// <param name="services">Service Collection</param>
        /// <param name="config">Application Configuration</param>
        /// <param name="serviceName">Name of service binding in Cloud Foundry</param>
        /// <param name="contextLifetime">Lifetime of the service to inject</param>
        /// <returns>IServiceCollection for chaining</returns>
        public static IServiceCollection AddDbContext <TContext>(this IServiceCollection services, IConfiguration config, string serviceName, ServiceLifetime contextLifetime = ServiceLifetime.Scoped)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (string.IsNullOrEmpty(serviceName))
            {
                throw new ArgumentNullException(nameof(serviceName));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var info = config.GetRequiredServiceInfo <MySqlServiceInfo>(serviceName);

            DoAdd(services, config, info, typeof(TContext), contextLifetime);

            return(services);
        }
        /// <summary>
        /// Add Oracle and its IHealthContributor to a ServiceCollection.
        /// </summary>
        /// <param name="services">Service collection to add to</param>
        /// <param name="config">App configuration</param>
        /// <param name="serviceName">cloud foundry service name binding</param>
        /// <param name="contextLifetime">Lifetime of the service to inject</param>
        /// <param name="addSteeltoeHealthChecks">Add steeltoeHealth checks even if community health checks exist</param>
        /// <returns>IServiceCollection for chaining</returns>
        /// <remarks>OracleConnection is retrievable as both OracleConnection and IDbConnection</remarks>
        public static IServiceCollection AddOracleConnection(this IServiceCollection services, IConfiguration config, string serviceName, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, bool addSteeltoeHealthChecks = false)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (string.IsNullOrEmpty(serviceName))
            {
                throw new ArgumentNullException(nameof(serviceName));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var info = config.GetRequiredServiceInfo <OracleServiceInfo>(serviceName);

            DoAdd(services, info, config, contextLifetime, addSteeltoeHealthChecks);
            return(services);
        }
Ejemplo n.º 13
0
 public ServiceDefinition(Type serviceType, ServiceLifetime serviceLifetime) : this(serviceType, serviceType, serviceLifetime)
 {
 }
Ejemplo n.º 14
0
 public ServiceDefinition(Type serviceType, Func <IServiceProvider, object> factory, ServiceLifetime serviceLifetime)
 {
     ServiceType           = serviceType;
     ImplementationFactory = factory;
     ServiceLifetime       = serviceLifetime;
 }
Ejemplo n.º 15
0
 public static IServiceCollection AddEventStorePipeline(this IServiceCollection services,
                                                        ServiceLifetime withLifetime = ServiceLifetime.Transient)
 {
     return(services.Add(typeof(INotificationHandler <>), typeof(EventStorePipeline <>), withLifetime));
 }
Ejemplo n.º 16
0
        private static void DoAdd(IServiceCollection services, PostgresServiceInfo info, IConfiguration config, ServiceLifetime contextLifetime, bool addSteeltoeHealthChecks)
        {
            var postgresConnection = ReflectionHelpers.FindType(PostgreSqlTypeLocator.Assemblies, PostgreSqlTypeLocator.ConnectionTypeNames);
            var postgresConfig     = new PostgresProviderConnectorOptions(config);
            var factory            = new PostgresProviderConnectorFactory(info, postgresConfig, postgresConnection);

            services.Add(new ServiceDescriptor(typeof(IDbConnection), factory.Create, contextLifetime));
            services.Add(new ServiceDescriptor(postgresConnection, factory.Create, contextLifetime));
            if (!services.Any(s => s.ServiceType == typeof(HealthCheckService)) || addSteeltoeHealthChecks)
            {
                services.Add(new ServiceDescriptor(typeof(IHealthContributor), ctx => new RelationalDbHealthContributor((IDbConnection)factory.Create(ctx), ctx.GetService <ILogger <RelationalDbHealthContributor> >()), ServiceLifetime.Singleton));
            }
        }
Ejemplo n.º 17
0
        public static void TryAddImplementors <T>(this IServiceCollection services,
                                                  IEnumerable <Assembly> assemblies = null, ServiceLifetime lifetime = ServiceLifetime.Transient)
        {
            assemblies ??= new[] { typeof(T).Assembly };

            var injectableTypes =
                assemblies.SelectMany(a =>
                                      a.DefinedTypes.Where(x => x.GetInterfaces().Contains(typeof(T)) && !x.IsAbstract));

            foreach (var type in injectableTypes)
            {
                services.TryAdd(new ServiceDescriptor(type, type, lifetime));
            }
        }
        private static IServiceCollection AddAutoMapperClasses(IServiceCollection services, Action <IServiceProvider, IMapperConfigurationExpression> configAction,
                                                               IEnumerable <Assembly> assembliesToScan, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
        {
            // Just return if we've already added AutoMapper to avoid double-registration
            if (services.Any(sd => sd.ServiceType == typeof(IMapper)))
            {
                return(services);
            }

            assembliesToScan = assembliesToScan as Assembly[] ?? assembliesToScan.ToArray();

            var allTypes = assembliesToScan
                           .Where(a => !a.IsDynamic && a.GetName().Name != nameof(AutoMapper))
                           .Distinct() // avoid AutoMapper.DuplicateTypeMapConfigurationException
                           .SelectMany(a => a.DefinedTypes)
                           .ToArray();

            void ConfigAction(IServiceProvider serviceProvider, IMapperConfigurationExpression cfg)
            {
                configAction?.Invoke(serviceProvider, cfg);

                cfg.AddMaps(assembliesToScan);
            }

            var openTypes = new[]
            {
                typeof(IValueResolver <, ,>),
                typeof(IMemberValueResolver <, , ,>),
                typeof(ITypeConverter <,>),
                typeof(IValueConverter <,>),
                typeof(IMappingAction <,>)
            };

            foreach (var type in openTypes.SelectMany(openType => allTypes
                                                      .Where(t => t.IsClass &&
                                                             !t.IsAbstract &&
                                                             t.AsType().ImplementsGenericInterface(openType))))
            {
                services.AddTransient(type.AsType());
            }

            services.AddSingleton <IConfigurationProvider>(sp => new MapperConfiguration(cfg => ConfigAction(sp, cfg)));
            services.Add(new ServiceDescriptor(typeof(IMapper),
                                               sp => new Mapper(sp.GetRequiredService <IConfigurationProvider>(), sp.GetService), serviceLifetime));

            return(services);
        }
 public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action <IServiceProvider, IMapperConfigurationExpression> configAction,
                                                IEnumerable <Type> profileAssemblyMarkerTypes, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
 => AddAutoMapperClasses(services, configAction, profileAssemblyMarkerTypes.Select(t => t.GetTypeInfo().Assembly), serviceLifetime);
 public static IServiceCollection AddAutoMapper(this IServiceCollection services, IEnumerable <Assembly> assemblies, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
 => AddAutoMapperClasses(services, null, assemblies, serviceLifetime);
 public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action <IServiceProvider, IMapperConfigurationExpression> configAction, IEnumerable <Assembly> assemblies, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
 => AddAutoMapperClasses(services, configAction, assemblies, serviceLifetime);
Ejemplo n.º 22
0
        public static IServiceCollection RegisterAssemblyTypes <T>(this IServiceCollection services, ServiceLifetime lifetime, List <Func <TypeInfo, bool> > predicates = null)
        {
            var scanAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();

            scanAssemblies.SelectMany(x => x.GetReferencedAssemblies())
            .Where(t => !scanAssemblies.Any(a => a.FullName == t.FullName))
            .Distinct()
            .ToList()
            .ForEach(x => scanAssemblies.Add(AppDomain.CurrentDomain.Load(x)));

            var interfaces = scanAssemblies
                             .SelectMany(o => o.DefinedTypes
                                         .Where(x => x.IsInterface && x != typeof(T) && typeof(T).IsAssignableFrom(x))
                                         );

            foreach (var @interface in interfaces)
            {
                var types = scanAssemblies
                            .SelectMany(o => o.DefinedTypes
                                        .Where(x => x.IsClass && @interface.IsAssignableFrom(x))
                                        );

                if (predicates?.Count() > 0)
                {
                    foreach (var predict in predicates)
                    {
                        types = types.Where(predict);
                    }
                }

                foreach (var type in types)
                {
                    services.Add(new ServiceDescriptor(
                                     @interface,
                                     type,
                                     lifetime));
                }
            }

            return(services);
        }
Ejemplo n.º 23
0
 public static IHostBuilder AddService <TService, TImplementation>(this IHostBuilder builder, ServiceLifetime lifetime = ServiceLifetime.Transient) where TService : class where TImplementation : class, TService
 {
     builder.ConfigureServices((hostContext, services) =>
     {
         services.Add(new ServiceDescriptor(typeof(TService), typeof(TImplementation), lifetime));
     });
     return(builder);
 }
Ejemplo n.º 24
0
 public ServiceDefinition(Type serviceType, Type implementType, ServiceLifetime serviceLifetime)
 {
     ServiceType     = serviceType;
     ImplementType   = implementType ?? serviceType;
     ServiceLifetime = serviceLifetime;
 }
Ejemplo n.º 25
0
 public static IHostBuilder AddService <TService>(this IHostBuilder builder, Func <IServiceProvider, object> factory, ServiceLifetime lifetime = ServiceLifetime.Transient) where TService : class
 {
     builder.ConfigureServices((hostContext, services) =>
     {
         services.Add(new ServiceDescriptor(typeof(TService), factory, lifetime));
     });
     return(builder);
 }
Ejemplo n.º 26
0
 public ServiceDescriptor(Type serviceType, Func <IServiceProvider, object> factory, ServiceLifetime lifetime)
 {
     implementationFactory  = factory;
     ImplementationInstance = null;
     ImplementationType     = serviceType;
     ServiceType            = serviceType;
     Lifetime = lifetime;
 }
 public OpenIddictValidationBuilder AddEventHandler <TEvent, THandler>(
     ServiceLifetime lifetime = ServiceLifetime.Scoped)
     where TEvent : class, IOpenIddictValidationEvent
     where THandler : IOpenIddictValidationEventHandler <TEvent>
 => AddEventHandler <TEvent>(typeof(THandler));
Ejemplo n.º 28
0
        private static void DoAdd(IServiceCollection services, IConfiguration config, MySqlServiceInfo info, Type dbContextType, ServiceLifetime contextLifetime)
        {
            var mySqlConfig = new MySqlProviderConnectorOptions(config);

            var factory = new MySqlDbContextConnectorFactory(info, mySqlConfig, dbContextType);

            services.Add(new ServiceDescriptor(dbContextType, factory.Create, contextLifetime));
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Register the tenant resolver implementation
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="lifetime"></param>
 /// <returns></returns>
 public TenantBuilder WithResolutionStrategy <T>(ServiceLifetime lifetime = ServiceLifetime.Transient)
     where T : class, ITenantResolutionStrategy
 {
     Services.Add(ServiceDescriptor.Describe(typeof(ITenantResolutionStrategy), typeof(T), lifetime));
     return(this);
 }
Ejemplo n.º 30
0
 /// <summary>
 /// Register the tenant store implementation
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="lifetime"></param>
 /// <returns></returns>
 public TenantBuilder WithStore <T>(ServiceLifetime lifetime = ServiceLifetime.Transient)
     where T : class, ITenantStore
 {
     Services.Add(ServiceDescriptor.Describe(typeof(ITenantStore), typeof(T), lifetime));
     return(this);
 }
Ejemplo n.º 31
0
 public virtual IDependencyRegistrationBuilder <TImplementation> AsTransient()
 {
     _serviceLifetime = ServiceLifetime.Transient;
     return(this);
 }
        private static Lifestyle ConvertLifetimeToSimpleInjectorLifetime(ServiceLifetime lifetime)
        {
            switch (lifetime)
            {
                case ServiceLifetime.Singleton:
                    return Lifestyle.Singleton;

                case ServiceLifetime.Scoped:
                    return Lifestyle.Scoped;

                case ServiceLifetime.Transient:
                    return Lifestyle.Transient;

                default:
                    throw new NotSupportedException();
            }
        }
        public void AddWithFactoryAddsServiceWithRightLifecyle(
            Action<IServiceCollection> addAction,
            Type serviceType,
            Type implementationType,
            ServiceLifetime lifeCycle)
        {
            // Arrange
            var collection = new ServiceCollection();

            // Act
            addAction(collection);

            // Assert
            var descriptor = Assert.Single(collection);
            Assert.Equal(serviceType, descriptor.ServiceType);
            Assert.Equal(implementationType, descriptor.GetImplementationType());
            Assert.Equal(lifeCycle, descriptor.Lifetime);
        }
 public ServiceDescriptorAttribute(Type serviceType, ServiceLifetime lifetime)
 {
     ServiceType = serviceType;
     Lifetime = lifetime;
 }
        public void TryAdd_WithType_AddsService(
            Action<IServiceCollection> addAction,
            Type expectedServiceType,
            Type expectedImplementationType,
            ServiceLifetime expectedLifetime)
        {
            // Arrange
            var collection = new ServiceCollection();

            // Act
            addAction(collection);

            // Assert
            var descriptor = Assert.Single(collection);
            Assert.Equal(expectedServiceType, descriptor.ServiceType);
            Assert.Same(expectedImplementationType, descriptor.ImplementationType);
            Assert.Equal(expectedLifetime, descriptor.Lifetime);
        }
Ejemplo n.º 36
0
 public virtual IDependencyRegistrationBuilder <TImplementation> AsScoped()
 {
     _serviceLifetime = ServiceLifetime.Scoped;
     return(this);
 }
Ejemplo n.º 37
0
 /// <summary>
 /// Adds the default services needed to run Piranha over
 /// Entity Framework Core.
 /// </summary>
 /// <param name="services">The current service collection</param>
 /// <param name="scope">The optional lifetime</param>
 /// <returns>The updated service collection</returns>
 public static IServiceCollection AddPiranhaEF(this IServiceCollection services,
                                               ServiceLifetime scope = ServiceLifetime.Scoped)
 {
     return(AddPiranhaEF <Db>(services, scope));
 }
        public void TryAddEnumerable_DoesNotAddDuplicate(
            ServiceDescriptor descriptor,
            Type expectedServiceType,
            Type expectedImplementationType,
            ServiceLifetime expectedLifetime)
        {
            // Arrange
            var collection = new ServiceCollection();
            collection.TryAddEnumerable(descriptor);

            // Act
            collection.TryAddEnumerable(descriptor);

            // Assert
            var d = Assert.Single(collection);
            Assert.Equal(expectedServiceType, d.ServiceType);
            Assert.Equal(expectedImplementationType, d.GetImplementationType());
            Assert.Equal(expectedLifetime, d.Lifetime);
        }
Ejemplo n.º 39
0
 public GivenAddServiceIsInvoked(ServiceScope declartionScope, ServiceLifetime expectedLifetime)
 {
     this.declartionScope  = declartionScope;
     this.expectedLifetime = expectedLifetime;
 }
        public void TryAdd_WithType_DoesNotAddDuplicate(
            Action<IServiceCollection> addAction,
            Type expectedServiceType,
            Type expectedImplementationType,
            ServiceLifetime expectedLifetime)
        {
            // Arrange
            var collection = new ServiceCollection();
            collection.Add(ServiceDescriptor.Transient(expectedServiceType, expectedServiceType));

            // Act
            addAction(collection);

            // Assert
            var descriptor = Assert.Single(collection);
            Assert.Equal(expectedServiceType, descriptor.ServiceType);
            Assert.Same(expectedServiceType, descriptor.ImplementationType);
            Assert.Equal(ServiceLifetime.Transient, descriptor.Lifetime);
        }
Ejemplo n.º 41
0
        /// <summary>
        /// Add an IHealthContributor to a ServiceCollection for MySQL
        /// </summary>
        /// <param name="services">Service collection to add to</param>
        /// <param name="config">App configuration</param>
        /// <param name="serviceName">cloud foundry service name binding</param>
        /// <param name="contextLifetime">Lifetime of the service to inject</param>
        /// <param name="logFactory">logger factory</param>
        /// <returns>IServiceCollection for chaining</returns>
        public static IServiceCollection AddMySqlHealthContributor(this IServiceCollection services, IConfiguration config, string serviceName, ServiceLifetime contextLifetime = ServiceLifetime.Singleton, ILoggerFactory logFactory = null)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (string.IsNullOrEmpty(serviceName))
            {
                throw new ArgumentNullException(nameof(serviceName));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            MySqlServiceInfo info = config.GetRequiredServiceInfo <MySqlServiceInfo>(serviceName);

            DoAdd(services, info, config, contextLifetime);
            return(services);
        }
Ejemplo n.º 42
0
        private static void DoAdd(IServiceCollection services, MySqlServiceInfo info, IConfiguration config, ServiceLifetime contextLifetime)
        {
            var mySqlConfig = new MySqlProviderConnectorOptions(config);
            var factory     = new MySqlProviderConnectorFactory(info, mySqlConfig, MySqlTypeLocator.MySqlConnection);

            services.Add(new ServiceDescriptor(typeof(IHealthContributor), ctx => new RelationalHealthContributor((IDbConnection)factory.Create(ctx), ctx.GetService <ILogger <RelationalHealthContributor> >()), contextLifetime));
        }
Ejemplo n.º 43
0
        /// <summary>
        /// Add NpgsqlConnection and its IHealthContributor to a ServiceCollection
        /// </summary>
        /// <param name="services">Service collection to add to</param>
        /// <param name="config">App configuration</param>
        /// <param name="contextLifetime">Lifetime of the service to inject</param>
        /// <param name="addSteeltoeHealthChecks">Add Steeltoe healthChecks</param>
        /// <returns>IServiceCollection for chaining</returns>
        /// <remarks>NpgsqlConnection is retrievable as both NpgsqlConnection and IDbConnection</remarks>
        public static IServiceCollection AddPostgresConnection(this IServiceCollection services, IConfiguration config, ServiceLifetime contextLifetime = ServiceLifetime.Scoped, bool addSteeltoeHealthChecks = false)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            var info = config.GetSingletonServiceInfo <PostgresServiceInfo>();

            DoAdd(services, info, config, contextLifetime, addSteeltoeHealthChecks);
            return(services);
        }