public static IServiceCollection AddMessageBusReceiver <T>(this IServiceCollection services, MessageBrokerOptions options)
        {
            if (options.UsedRabbitMQ())
            {
                services.AddRabbitMQReceiver <T>(options.RabbitMQ);
            }
            else if (options.UsedKafka())
            {
                services.AddKafkaReceiver <T>(options.Kafka);
            }
            else if (options.UsedAzureQueue())
            {
                services.AddAzureQueueReceiver <T>(options.AzureQueue);
            }
            else if (options.UsedAzureServiceBus())
            {
                services.AddAzureServiceBusReceiver <T>(options.AzureServiceBus);
            }
            else if (options.UsedAzureEventHub())
            {
                services.AddAzureEventHubReceiver <T>(options.AzureEventHub);
            }
            else if (options.UsedFake())
            {
                services.AddFakeReceiver <T>();
            }

            return(services);
        }
        public static IServiceCollection AddStorageModule(this IServiceCollection services, StorageOptions storageOptions, MessageBrokerOptions messageBrokerOptions, string connectionString, string migrationsAssembly = "")
        {
            services.AddDbContext <StorageDbContext>(options => options.UseSqlServer(connectionString, sql =>
            {
                if (!string.IsNullOrEmpty(migrationsAssembly))
                {
                    sql.MigrationsAssembly(migrationsAssembly);
                }
            }))
            .AddScoped <IRepository <FileEntry, Guid>, Repository <FileEntry, Guid> >();

            DomainEvents.RegisterHandlers(Assembly.GetExecutingAssembly(), services);

            services.AddMessageHandlers(Assembly.GetExecutingAssembly());

            if (storageOptions.UsedAzure())
            {
                services.AddSingleton <IFileStorageManager>(new AzureBlobStorageManager(storageOptions.Azure.ConnectionString, storageOptions.Azure.Container));
            }
            else if (storageOptions.UsedAmazon())
            {
                services.AddSingleton <IFileStorageManager>(
                    new AmazonS3StorageManager(
                        storageOptions.Amazon.AccessKeyID,
                        storageOptions.Amazon.SecretAccessKey,
                        storageOptions.Amazon.BucketName,
                        storageOptions.Amazon.RegionEndpoint));
            }
            else
            {
                services.AddSingleton <IFileStorageManager>(new LocalFileStorageManager(storageOptions.Local.Path));
            }

            if (messageBrokerOptions.UsedRabbitMQ())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new RabbitMQSender <FileUploadedEvent>(new RabbitMQSenderOptions
                {
                    HostName     = messageBrokerOptions.RabbitMQ.HostName,
                    UserName     = messageBrokerOptions.RabbitMQ.UserName,
                    Password     = messageBrokerOptions.RabbitMQ.Password,
                    ExchangeName = messageBrokerOptions.RabbitMQ.ExchangeName,
                    RoutingKey   = messageBrokerOptions.RabbitMQ.RoutingKey_FileUploaded,
                }));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new RabbitMQSender <FileDeletedEvent>(new RabbitMQSenderOptions
                {
                    HostName     = messageBrokerOptions.RabbitMQ.HostName,
                    UserName     = messageBrokerOptions.RabbitMQ.UserName,
                    Password     = messageBrokerOptions.RabbitMQ.Password,
                    ExchangeName = messageBrokerOptions.RabbitMQ.ExchangeName,
                    RoutingKey   = messageBrokerOptions.RabbitMQ.RoutingKey_FileDeleted,
                }));
            }
            else if (messageBrokerOptions.UsedKafka())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new KafkaSender <FileUploadedEvent>(
                                                                                messageBrokerOptions.Kafka.BootstrapServers,
                                                                                messageBrokerOptions.Kafka.Topic_FileUploaded));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new KafkaSender <FileDeletedEvent>(
                                                                               messageBrokerOptions.Kafka.BootstrapServers,
                                                                               messageBrokerOptions.Kafka.Topic_FileDeleted));
            }
            else if (messageBrokerOptions.UsedAzureQueue())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new AzureQueueSender <FileUploadedEvent>(
                                                                                connectionString: messageBrokerOptions.AzureQueue.ConnectionString,
                                                                                queueName: messageBrokerOptions.AzureQueue.QueueName_FileUploaded));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new AzureQueueSender <FileDeletedEvent>(
                                                                               connectionString: messageBrokerOptions.AzureQueue.ConnectionString,
                                                                               queueName: messageBrokerOptions.AzureQueue.QueueName_FileDeleted));
            }
            else if (messageBrokerOptions.UsedAzureServiceBus())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new AzureServiceBusSender <FileUploadedEvent>(
                                                                                connectionString: messageBrokerOptions.AzureServiceBus.ConnectionString,
                                                                                queueName: messageBrokerOptions.AzureServiceBus.QueueName_FileUploaded));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new AzureServiceBusSender <FileDeletedEvent>(
                                                                               connectionString: messageBrokerOptions.AzureServiceBus.ConnectionString,
                                                                               queueName: messageBrokerOptions.AzureServiceBus.QueueName_FileDeleted));
            }
            else if (messageBrokerOptions.UsedAzureEventGrid())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new AzureEventGridSender <FileUploadedEvent>(
                                                                                messageBrokerOptions.AzureEventGrid.DomainEndpoint,
                                                                                messageBrokerOptions.AzureEventGrid.DomainKey,
                                                                                messageBrokerOptions.AzureEventGrid.Topic_FileUploaded));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new AzureEventGridSender <FileDeletedEvent>(
                                                                               messageBrokerOptions.AzureEventGrid.DomainEndpoint,
                                                                               messageBrokerOptions.AzureEventGrid.DomainKey,
                                                                               messageBrokerOptions.AzureEventGrid.Topic_FileDeleted));
            }
            else if (messageBrokerOptions.UsedAzureEventHub())
            {
                services.AddSingleton <IMessageSender <FileUploadedEvent> >(new AzureEventHubSender <FileUploadedEvent>(
                                                                                messageBrokerOptions.AzureEventHub.ConnectionString,
                                                                                messageBrokerOptions.AzureEventHub.Hub_FileUploaded));

                services.AddSingleton <IMessageSender <FileDeletedEvent> >(new AzureEventHubSender <FileDeletedEvent>(
                                                                               messageBrokerOptions.AzureEventHub.ConnectionString,
                                                                               messageBrokerOptions.AzureEventHub.Hub_FileDeleted));
            }

            return(services);
        }
        public static IServiceCollection AddMessageBusSender <T>(this IServiceCollection services, MessageBrokerOptions options, IHealthChecksBuilder healthChecksBuilder = null, HashSet <string> checkDulicated = null)
        {
            if (options.UsedRabbitMQ())
            {
                services.AddRabbitMQSender <T>(options.RabbitMQ);

                if (healthChecksBuilder != null)
                {
                    var name = "Message Broker (RabbitMQ)";

                    if (checkDulicated == null || !checkDulicated.Contains(name))
                    {
                        healthChecksBuilder.AddRabbitMQ(
                            rabbitMQConnectionString: options.RabbitMQ.ConnectionString,
                            name: name,
                            failureStatus: HealthStatus.Degraded);
                    }

                    checkDulicated?.Add(name);
                }
            }
            else if (options.UsedKafka())
            {
                services.AddKafkaSender <T>(options.Kafka);

                if (healthChecksBuilder != null)
                {
                    var name = "Message Broker (Kafka)";

                    if (checkDulicated == null || !checkDulicated.Contains(name))
                    {
                        healthChecksBuilder.AddKafka(
                            setup =>
                        {
                            setup.BootstrapServers = options.Kafka.BootstrapServers;
                            setup.MessageTimeoutMs = 5000;
                        },
                            name: name,
                            failureStatus: HealthStatus.Degraded);
                    }

                    checkDulicated?.Add(name);
                }
            }
            else if (options.UsedAzureQueue())
            {
                services.AddAzureQueueSender <T>(options.AzureQueue);

                if (healthChecksBuilder != null)
                {
                    healthChecksBuilder.AddAzureQueueStorage(connectionString: options.AzureQueue.ConnectionString,
                                                             queueName: options.AzureQueue.QueueNames[typeof(T).Name],
                                                             name: $"Message Broker (Azure Queue) {typeof(T).Name}",
                                                             failureStatus: HealthStatus.Degraded);
                }
            }
            else if (options.UsedAzureServiceBus())
            {
                services.AddAzureServiceBusSender <T>(options.AzureServiceBus);

                if (healthChecksBuilder != null)
                {
                    healthChecksBuilder.AddAzureServiceBusQueue(
                        connectionString: options.AzureServiceBus.ConnectionString,
                        queueName: options.AzureServiceBus.QueueNames[typeof(T).Name],
                        name: $"Message Broker (Azure Service Bus) {typeof(T).Name}",
                        failureStatus: HealthStatus.Degraded);
                }
            }
            else if (options.UsedAzureEventGrid())
            {
                services.AddAzureEventGridSender <T>(options.AzureEventGrid);

                // TODO: Add Health Check
            }
            else if (options.UsedAzureEventHub())
            {
                services.AddAzureEventHubSender <T>(options.AzureEventHub);

                // TODO: Add Health Check
            }
            else if (options.UsedFake())
            {
                services.AddFakeSender <T>();
            }

            return(services);
        }