/// <summary>
        /// Use default implementation of IAuditSubject and IAuditAction.
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddDefaultEventData(this IAuditLoggingBuilder builder)
        {
            builder.Services.AddTransient <IAuditSubject, DefaultAuditSubject>();
            builder.Services.AddTransient <IAuditAction, DefaultAuditAction>();

            return(builder);
        }
        /// <summary>
        /// Use IAuditSubject with pre-defined static data. This might be useful for service which is running as machine app.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="defaultAuditSubject"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddStaticEventSubject(this IAuditLoggingBuilder builder, Action <DefaultAuditSubject> defaultAuditSubject)
        {
            var auditSubject = new DefaultAuditSubject();

            defaultAuditSubject?.Invoke(auditSubject);
            builder.Services.AddSingleton <IAuditSubject>(auditSubject);

            return(builder);
        }
        public static IAuditLoggingBuilder AddAuditSinks <T1>(this IAuditLoggingBuilder builder)
            where T1 : class, IAuditEventLoggerSink
        {
            builder.Services.TryAddEnumerable(new[]
            {
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T1>(),
            });

            return(builder);
        }
        /// <summary>
        /// Add audit default data - subject and action
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="subjectOptions"></param>
        /// <param name="actionOptions"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddDefaultHttpEventData(this IAuditLoggingBuilder builder, Action <AuditHttpSubjectOptions> subjectOptions = default, Action <AuditHttpActionOptions> actionOptions = default)
        {
            var auditHttpSubjectOptions = new AuditHttpSubjectOptions();

            subjectOptions?.Invoke(auditHttpSubjectOptions);
            builder.Services.AddSingleton(auditHttpSubjectOptions);

            var auditHttpActionOptions = new AuditHttpActionOptions();

            actionOptions?.Invoke(auditHttpActionOptions);
            builder.Services.AddSingleton(auditHttpActionOptions);

            builder.Services.AddTransient <IAuditSubject, HttpAuditSubject>();
            builder.Services.AddTransient <IAuditAction, HttpAuditAction>();

            return(builder);
        }
        public static IAuditLoggingBuilder AddAuditSinks <T1, T2, T3, T4, T5>(this IAuditLoggingBuilder builder)
            where T1 : class, IAuditEventLoggerSink
            where T2 : class, IAuditEventLoggerSink
            where T3 : class, IAuditEventLoggerSink
            where T4 : class, IAuditEventLoggerSink
            where T5 : class, IAuditEventLoggerSink
        {
            builder.Services.TryAddEnumerable(new[]
            {
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T1>(),
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T2>(),
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T3>(),
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T4>(),
                ServiceDescriptor.Transient <IAuditEventLoggerSink, T5>()
            });

            return(builder);
        }
        /// <summary>
        /// Add own implementation for event data
        /// </summary>
        /// <typeparam name="TEventSubject"></typeparam>
        /// <typeparam name="TEventAction"></typeparam>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddEventData <TEventSubject, TEventAction>(this IAuditLoggingBuilder builder)
            where TEventSubject : class, IAuditSubject
            where TEventAction : class, IAuditAction
        {
            builder.Services.AddTransient <IAuditSubject, TEventSubject>();
            builder.Services.AddTransient <IAuditAction, TEventAction>();

            return(builder);
        }
        /// <summary>
        /// Add default database audit sink
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddDefaultAuditSink(this IAuditLoggingBuilder builder)
        {
            builder.AddAuditSinks <DatabaseAuditEventLoggerSink <AuditLog> >();

            return(builder);
        }
        /// <summary>
        /// Add store with DbContext and Repository
        /// </summary>
        /// <typeparam name="TDbContext"></typeparam>
        /// <typeparam name="TAuditLoggingRepository"></typeparam>
        /// <typeparam name="TAuditLog"></typeparam>
        /// <param name="builder"></param>
        /// <param name="dbContextOptions"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddStore <TDbContext, TAuditLog, TAuditLoggingRepository>(this IAuditLoggingBuilder builder, Action <DbContextOptionsBuilder> dbContextOptions)
            where TDbContext : DbContext, IAuditLoggingDbContext <TAuditLog> where TAuditLoggingRepository : class, IAuditLoggingRepository <TAuditLog> where TAuditLog : AuditLog
        {
            builder.Services.AddDbContext <TDbContext>(dbContextOptions);
            builder.Services.AddTransient <IAuditLoggingRepository <TAuditLog>, TAuditLoggingRepository>();

            return(builder);
        }
        /// <summary>
        /// Add default DbContext and Repository
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="dbContextOptions"></param>
        /// <returns></returns>
        public static IAuditLoggingBuilder AddDefaultStore(this IAuditLoggingBuilder builder, Action <DbContextOptionsBuilder> dbContextOptions)
        {
            builder.AddStore <DefaultAuditLoggingDbContext, AuditLog, AuditLoggingRepository <DefaultAuditLoggingDbContext, AuditLog> >(dbContextOptions);

            return(builder);
        }