public RecurringHostedService(ILogger <RecurringHostedService <TService> > logger,
                               IServiceScopeFactory serviceScopeFactory,
                               RecurringServiceOptionsCollection optionsCollection)
 {
     _logger = logger;
     _serviceScopeFactory = serviceScopeFactory;
     _optionsCollection   = optionsCollection;
 }
        /// <summary>
        /// Registers a recurring task which will be triggered according to the TimeSpan parameter. A service class may not be registered multiple times.
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="services"></param>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">When <paramref name="timeSpan"/> is less than one second.</exception>
        public static IServiceCollection AddRecurringTask <TService>(this IServiceCollection services, TimeSpan timeSpan) where TService : class, IRecurringService
        {
            // validate the timespan
            if (timeSpan.TotalSeconds < 1)
            {
                throw new ArgumentException("TimeSpan must be greater than 1 second.", nameof(timeSpan));
            }

            // if the options collection is not yet registered, then register as a singleton
            ServiceDescriptor collectionServiceDescriptor = services
                                                            .Where(e => e.Lifetime == ServiceLifetime.Singleton)
                                                            .Where(e => e.ServiceType == typeof(RecurringServiceOptionsCollection))
                                                            .FirstOrDefault();
            RecurringServiceOptionsCollection optionsCollection = null;

            if (collectionServiceDescriptor == null)
            {
                optionsCollection = new RecurringServiceOptionsCollection();
                services.AddSingleton(typeof(RecurringServiceOptionsCollection), optionsCollection);
            }
            else
            {
                optionsCollection = collectionServiceDescriptor.ImplementationInstance as RecurringServiceOptionsCollection;
            }

            // validate the type doesn't already exist
            if (optionsCollection.TypeOptions.ContainsKey(typeof(TService)))
            {
                throw new InvalidOperationException($"The type {typeof(TService)} has already been registered as a recurring task. A type may only be registered one time.");
            }
            optionsCollection.TypeOptions.Add(typeof(TService), new RecurringServiceOptions()
            {
                TimeSpan = timeSpan
            });

            // register the primary hosted service
            services.AddHostedService <RecurringHostedService <TService> >();

            // register the service itself as transient so the hosted service can instantiate each run
            services.AddTransient <TService>();

            return(services);
        }