diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..1702ddc
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [1.11.0] - 2026-02-06
+
+### Added
+
+- Added two overloads for Dependency injection offering the use of a custom configuration type for Table and View repositories respectively.
+ - This can be useful if you want to add extra configuration to your repos and don't want to deal with the overload taking a constructor delegate.
\ No newline at end of file
diff --git a/Dapper.DDD.Repository.sln b/Dapper.DDD.Repository.sln
index 1a36a67..4682726 100644
--- a/Dapper.DDD.Repository.sln
+++ b/Dapper.DDD.Repository.sln
@@ -28,6 +28,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
+ CHANGELOG.md = CHANGELOG.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapper.DDD.Repository.PostGreSql", "src\Dapper.DDD.Repository.PostGreSql\Dapper.DDD.Repository.PostGreSql.csproj", "{92DAD05A-C310-40D0-BB38-D27C4B565EC3}"
diff --git a/Directory.Build.props b/Directory.Build.props
index c3197d6..de8bf99 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,7 +1,7 @@
- 1.10.3
+ 1.11.0
diff --git a/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection.cs b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection.cs
index e535c3f..5389d55 100644
--- a/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection.cs
+++ b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection.cs
@@ -1,21 +1,6 @@
-using Dapper.DDD.Repository.Configuration;
-using Dapper.DDD.Repository.Interfaces;
-using Dapper.DDD.Repository.Repositories;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
-
namespace Dapper.DDD.Repository.DependencyInjection;
-public delegate TRepository TableRepositoryConstructorDelegate(
- IOptions> options, IOptions? defaultOptions, IServiceProvider provider)
- where TAggregate : notnull;
-
-public delegate TRepository ViewRepositoryConstructorDelegate(
- IOptions> options, IOptions? defaultOptions,
- IServiceProvider provider)
- where TAggregate : notnull;
-
-public static class DapperRepositoryDependencyInjection
+public static partial class DapperRepositoryDependencyInjection
{
///
/// Configure defaults to use for all aggregate types.
@@ -25,195 +10,4 @@ public static IServiceCollection ConfigureDapperRepositoryDefaults(this IService
{
return services.Configure(configureOptions);
}
-
- ///
- /// Add a table repository for the given aggregate type to the dependency injection system.
- /// You can request an ITableRepository through the dependency injection system afterwards.
- ///
- public static IServiceCollection AddTableRepository(this IServiceCollection services,
- Action> configureOptions)
- where TAggregate : notnull
- where TAggregateId : notnull
- {
- services.Configure(configureOptions);
- services
- .AddSingleton, TableRepository>();
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// You can request an IViewRepository through the dependency injection system afterwards.
- ///
- public static IServiceCollection AddViewRepository(this IServiceCollection services,
- Action> configureOptions)
- where TAggregate : notnull
- where TAggregateId : notnull
- {
- services.Configure(configureOptions);
- services
- .AddSingleton, ViewRepository>();
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// You can request an IViewRepository through the dependency injection system afterwards.
- ///
- public static IServiceCollection AddViewRepository(this IServiceCollection services,
- Action> configureOptions)
- where TAggregate : notnull
- {
- services.Configure(configureOptions);
- services.AddSingleton, ViewRepository>();
- return services;
- }
-
- ///
- /// Add a table repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in TableRepository type.
- ///
- /// Type of your aggregate
- /// Type of your aggregate's Id
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddTableRepository(this IServiceCollection services,
- Action> configureOptions)
- where TAggregate : notnull
- where TAggregateId : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : TableRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton();
- return services;
- }
-
-
- ///
- /// Add a table repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in TableRepository type.
- /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
- ///
- /// Type of your aggregate
- /// Type of your aggregate's Id
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddTableRepository(this IServiceCollection services,
- Action> configureOptions,
- TableRepositoryConstructorDelegate constructor)
- where TAggregate : notnull
- where TAggregateId : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : TableRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton(provider =>
- {
- var configuration = provider.GetRequiredService>>();
- var defaultConfiguration = provider.GetService>();
- return constructor(configuration, defaultConfiguration, provider);
- });
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
- ///
- /// Type of your aggregate
- /// Type of your aggregate's Id
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddViewRepository(this IServiceCollection services,
- Action> configureOptions)
- where TAggregate : notnull
- where TAggregateId : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : ViewRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton();
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
- /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
- ///
- /// Type of your aggregate
- /// Type of your aggregate's Id
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddViewRepository(this IServiceCollection services,
- Action> configureOptions,
- ViewRepositoryConstructorDelegate constructor)
- where TAggregate : notnull
- where TAggregateId : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : ViewRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton(provider =>
- {
- var configuration = provider.GetRequiredService>>();
- var defaultConfiguration = provider.GetService>();
- return constructor(configuration, defaultConfiguration, provider);
- });
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
- ///
- /// Type of your aggregate
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddViewRepository(
- this IServiceCollection services, Action> configureOptions)
- where TAggregate : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : ViewRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton();
- return services;
- }
-
- ///
- /// Add a view repository for the given aggregate type to the dependency injection system.
- /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
- /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
- ///
- /// Type of your aggregate
- /// Interface type of your repository
- /// Actual implementation type of your repository
- /// Used to configure the repository via lambda
- public static IServiceCollection AddViewRepository(
- this IServiceCollection services, Action> configureOptions,
- ViewRepositoryConstructorDelegate constructor)
- where TAggregate : notnull
- where TRepositoryInterface : class
- where TRepositoryClass : ViewRepository, TRepositoryInterface
- {
- services.Configure(configureOptions);
- services.AddSingleton(provider =>
- {
- var configuration = provider.GetRequiredService>>();
- var defaultConfiguration = provider.GetService>();
- return constructor(configuration, defaultConfiguration, provider);
- });
- return services;
- }
}
\ No newline at end of file
diff --git a/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_Table.cs b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_Table.cs
new file mode 100644
index 0000000..1317c15
--- /dev/null
+++ b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_Table.cs
@@ -0,0 +1,109 @@
+namespace Dapper.DDD.Repository.DependencyInjection;
+
+public delegate TRepository TableRepositoryConstructorDelegate(
+ IOptions> options, IOptions? defaultOptions, IServiceProvider provider)
+ where TAggregate : notnull;
+
+public static partial class DapperRepositoryDependencyInjection
+{
+ ///
+ /// Add a table repository for the given aggregate type to the dependency injection system.
+ /// You can request an ITableRepository through the dependency injection system afterwards.
+ ///
+ public static IServiceCollection AddTableRepository(this IServiceCollection services,
+ Action> configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ {
+ services.Configure(configureOptions);
+ services
+ .AddSingleton, TableRepository>();
+ return services;
+ }
+
+ ///
+ /// Add a table repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in TableRepository type.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddTableRepository(this IServiceCollection services,
+ Action> configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : TableRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton();
+ return services;
+ }
+
+ ///
+ /// Add a table repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in TableRepository type.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ ///
+ /// Custom type of configuration for your repository, useful if you want to append custom
+ /// configuration. Your repository constructor should expect this type instead of TableAggregateConfiguration<
+ /// TAggregate>.
+ ///
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddTableRepository(this IServiceCollection services,
+ Action configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : TableRepository, TRepositoryInterface
+ where TConfiguration : TableAggregateConfiguration, new()
+ {
+ var ctorInfo = typeof(TRepositoryClass).GetConstructor([typeof(IOptions), typeof(IOptions)]);
+ if (ctorInfo is null || ctorInfo.GetParameters()[0].ParameterType != typeof(IOptions))
+ {
+ throw new ArgumentException($"The constructor for {typeof(TRepositoryClass).Name} does not take IOptions<{typeof(TConfiguration).Name}> as argument!", nameof(configureOptions));
+ }
+
+ services.Configure(configureOptions);
+ services.AddSingleton();
+ return services;
+ }
+
+
+ ///
+ /// Add a table repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in TableRepository type.
+ /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddTableRepository(this IServiceCollection services,
+ Action> configureOptions,
+ TableRepositoryConstructorDelegate constructor)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : TableRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton(provider =>
+ {
+ var configuration = provider.GetRequiredService>>();
+ var defaultConfiguration = provider.GetService>();
+ return constructor(configuration, defaultConfiguration, provider);
+ });
+ return services;
+ }
+}
\ No newline at end of file
diff --git a/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_View.cs b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_View.cs
new file mode 100644
index 0000000..4279ac3
--- /dev/null
+++ b/src/Dapper.DDD.Repository.DependencyInjection/DapperRepositoryDependencyInjection_View.cs
@@ -0,0 +1,167 @@
+namespace Dapper.DDD.Repository.DependencyInjection;
+
+public delegate TRepository ViewRepositoryConstructorDelegate(
+ IOptions> options, IOptions? defaultOptions,
+ IServiceProvider provider)
+ where TAggregate : notnull;
+
+public static partial class DapperRepositoryDependencyInjection
+{
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// You can request an IViewRepository through the dependency injection system afterwards.
+ ///
+ public static IServiceCollection AddViewRepository(this IServiceCollection services,
+ Action> configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ {
+ services.Configure(configureOptions);
+ services
+ .AddSingleton, ViewRepository>();
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// You can request an IViewRepository through the dependency injection system afterwards.
+ ///
+ public static IServiceCollection AddViewRepository(this IServiceCollection services,
+ Action> configureOptions)
+ where TAggregate : notnull
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton, ViewRepository>();
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddViewRepository(this IServiceCollection services,
+ Action> configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : ViewRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton();
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ ///
+ /// Custom type of configuration for your repository, useful if you want to append custom
+ /// configuration. Your repository constructor should expect this type instead of ViewAggregateConfiguration<
+ /// TAggregate>.
+ ///
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddViewRepository(this IServiceCollection services,
+ Action configureOptions)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : ViewRepository, TRepositoryInterface
+ where TConfiguration : ViewAggregateConfiguration, new()
+ {
+ var ctorInfo = typeof(TRepositoryClass).GetConstructor([typeof(IOptions), typeof(IOptions)]);
+ if (ctorInfo is null || ctorInfo.GetParameters()[0].ParameterType != typeof(IOptions))
+ {
+ throw new ArgumentException($"The constructor for {typeof(TRepositoryClass).Name} does not take IOptions<{typeof(TConfiguration).Name}> as argument!", nameof(configureOptions));
+ }
+
+ services.Configure(configureOptions);
+ services.AddSingleton();
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
+ /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
+ ///
+ /// Type of your aggregate
+ /// Type of your aggregate's Id
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddViewRepository(this IServiceCollection services,
+ Action> configureOptions,
+ ViewRepositoryConstructorDelegate constructor)
+ where TAggregate : notnull
+ where TAggregateId : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : ViewRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton(provider =>
+ {
+ var configuration = provider.GetRequiredService>>();
+ var defaultConfiguration = provider.GetService>();
+ return constructor(configuration, defaultConfiguration, provider);
+ });
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
+ ///
+ /// Type of your aggregate
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddViewRepository(
+ this IServiceCollection services, Action> configureOptions)
+ where TAggregate : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : ViewRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton();
+ return services;
+ }
+
+ ///
+ /// Add a view repository for the given aggregate type to the dependency injection system.
+ /// Uses a custom class and interface, allowing you to inherit from the built-in ViewRepository type.
+ /// Takes a custom function to create the actual instance, allowing you to set any instance-specific state.
+ ///
+ /// Type of your aggregate
+ /// Interface type of your repository
+ /// Actual implementation type of your repository
+ /// Used to configure the repository via lambda
+ public static IServiceCollection AddViewRepository(
+ this IServiceCollection services, Action> configureOptions,
+ ViewRepositoryConstructorDelegate constructor)
+ where TAggregate : notnull
+ where TRepositoryInterface : class
+ where TRepositoryClass : ViewRepository, TRepositoryInterface
+ {
+ services.Configure(configureOptions);
+ services.AddSingleton(provider =>
+ {
+ var configuration = provider.GetRequiredService>>();
+ var defaultConfiguration = provider.GetService>();
+ return constructor(configuration, defaultConfiguration, provider);
+ });
+ return services;
+ }
+}
\ No newline at end of file
diff --git a/src/Dapper.DDD.Repository.DependencyInjection/GlobalUsings.cs b/src/Dapper.DDD.Repository.DependencyInjection/GlobalUsings.cs
new file mode 100644
index 0000000..68c1877
--- /dev/null
+++ b/src/Dapper.DDD.Repository.DependencyInjection/GlobalUsings.cs
@@ -0,0 +1,7 @@
+// Global using directives
+
+global using Dapper.DDD.Repository.Configuration;
+global using Dapper.DDD.Repository.Interfaces;
+global using Dapper.DDD.Repository.Repositories;
+global using Microsoft.Extensions.DependencyInjection;
+global using Microsoft.Extensions.Options;
\ No newline at end of file
diff --git a/src/Dapper.DDD.Repository/Dapper.DDD.Repository.csproj b/src/Dapper.DDD.Repository/Dapper.DDD.Repository.csproj
index f2bbd87..ee12582 100644
--- a/src/Dapper.DDD.Repository/Dapper.DDD.Repository.csproj
+++ b/src/Dapper.DDD.Repository/Dapper.DDD.Repository.csproj
@@ -18,6 +18,7 @@
+
diff --git a/tests/Dapper.DDD.Repository.MySql.IntegrationTests/Configuration/ContainerFixture.cs b/tests/Dapper.DDD.Repository.MySql.IntegrationTests/Configuration/ContainerFixture.cs
index 0a1184b..17c4dc7 100644
--- a/tests/Dapper.DDD.Repository.MySql.IntegrationTests/Configuration/ContainerFixture.cs
+++ b/tests/Dapper.DDD.Repository.MySql.IntegrationTests/Configuration/ContainerFixture.cs
@@ -70,7 +70,7 @@ public async ValueTask DisposeAsync()
private async Task InitializeTestContainerAsync()
{
- _container = new MySqlBuilder()
+ _container = new MySqlBuilder("mysql:latest")
.WithDatabase("northwind")
.Build();
diff --git a/tests/Dapper.DDD.Repository.Sql.IntegrationTests/Configuration/ContainerFixture.cs b/tests/Dapper.DDD.Repository.Sql.IntegrationTests/Configuration/ContainerFixture.cs
index f389fa1..f75d386 100644
--- a/tests/Dapper.DDD.Repository.Sql.IntegrationTests/Configuration/ContainerFixture.cs
+++ b/tests/Dapper.DDD.Repository.Sql.IntegrationTests/Configuration/ContainerFixture.cs
@@ -102,8 +102,7 @@ public async ValueTask DisposeAsync()
private async Task InitializeTestContainerAsync()
{
- _container = new MsSqlBuilder()
- .WithImage("mcr.microsoft.com/mssql/server:2022-latest")
+ _container = new MsSqlBuilder("mcr.microsoft.com/mssql/server:2022-latest")
.WithWaitStrategy(Wait.ForUnixContainer().UntilInternalTcpPortIsAvailable(MsSqlBuilder.MsSqlPort))
.Build();
diff --git a/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_TableTests.cs b/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_TableTests.cs
new file mode 100644
index 0000000..dc81d29
--- /dev/null
+++ b/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_TableTests.cs
@@ -0,0 +1,72 @@
+using Dapper.DDD.Repository.DependencyInjection;
+using Dapper.DDD.Repository.Repositories;
+
+namespace Dapper.DDD.Repository.UnitTests.DependencyInjection;
+
+public partial class DapperRepositoryDependencyInjectionTests
+{
+ [Fact]
+ public void AddTableRepository_CustomConfigurationWithMismatchedConstructor_Throws()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+
+ // Act && Assert
+ var ex = Assert.Throws(() => { services.AddTableRepository(_ => { }); });
+
+ Assert.Contains($"The constructor for {typeof(UserRepositoryWithWrongConstructor).Name} does not take IOptions<{typeof(CustomConfig).Name}> as argument!", ex.Message);
+ }
+
+ [Fact]
+ public void AddTableRepository_CustomConfigurationWithProperConstructor_ReceivesCustomConfig()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var guid = Guid.NewGuid();
+
+ // Act
+ services.AddTableRepository(config =>
+ {
+ config.ConnectionFactory = Substitute.For();
+ config.DapperInjectionFactory = Substitute.For();
+ config.QueryGeneratorFactory = new MockQueryGeneratorFactory();
+ config.CustomArgument = guid;
+ config.HasKey(e => e.Id);
+ config.TableName = "Users";
+ });
+ var provider = services.BuildServiceProvider();
+
+ // Assert
+ var repo = provider.GetRequiredService() as UserRepositoryWithRightConstructor;
+ Assert.NotNull(repo);
+ Assert.Equal(guid, repo.CustomArgument);
+ }
+
+ public record User(Guid Id, string Name);
+}
+
+file class CustomConfig : TableAggregateConfiguration
+{
+ public Guid CustomArgument { get; set; }
+}
+
+file interface IUserRepository : ITableRepository
+{
+}
+
+file class UserRepositoryWithWrongConstructor : TableRepository, IUserRepository
+{
+ public UserRepositoryWithWrongConstructor(IOptions> options, IOptions? defaultOptions) : base(options, defaultOptions)
+ {
+ }
+}
+
+file class UserRepositoryWithRightConstructor : TableRepository, IUserRepository
+{
+ public UserRepositoryWithRightConstructor(IOptions options, IOptions? defaultOptions) : base(options, defaultOptions)
+ {
+ CustomArgument = options.Value.CustomArgument;
+ }
+
+ public Guid CustomArgument { get; }
+}
\ No newline at end of file
diff --git a/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_ViewTests.cs b/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_ViewTests.cs
new file mode 100644
index 0000000..be6f4e4
--- /dev/null
+++ b/tests/Dapper.DDD.Repository.UnitTests/DependencyInjection/DapperRepositoryDependencyInjection_ViewTests.cs
@@ -0,0 +1,70 @@
+using Dapper.DDD.Repository.DependencyInjection;
+using Dapper.DDD.Repository.Repositories;
+
+namespace Dapper.DDD.Repository.UnitTests.DependencyInjection;
+
+public partial class DapperRepositoryDependencyInjectionTests
+{
+ [Fact]
+ public void AddViewRepository_CustomConfigurationWithMismatchedConstructor_Throws()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+
+ // Act && Assert
+ var ex = Assert.Throws(() => { services.AddViewRepository(_ => { }); });
+
+ Assert.Contains($"The constructor for {typeof(UserRepositoryWithWrongConstructor).Name} does not take IOptions<{typeof(CustomConfig).Name}> as argument!", ex.Message);
+ }
+
+ [Fact]
+ public void AddViewRepository_CustomConfigurationWithProperConstructor_ReceivesCustomConfig()
+ {
+ // Arrange
+ var services = new ServiceCollection();
+ var guid = Guid.NewGuid();
+
+ // Act
+ services.AddViewRepository(config =>
+ {
+ config.ConnectionFactory = Substitute.For();
+ config.DapperInjectionFactory = Substitute.For();
+ config.QueryGeneratorFactory = new MockQueryGeneratorFactory();
+ config.CustomArgument = guid;
+ config.HasKey(e => e.Id);
+ config.ViewName = "Users";
+ });
+ var provider = services.BuildServiceProvider();
+
+ // Assert
+ var repo = provider.GetRequiredService() as UserRepositoryWithRightConstructor;
+ Assert.NotNull(repo);
+ Assert.Equal(guid, repo.CustomArgument);
+ }
+}
+
+file class CustomConfig : ViewAggregateConfiguration
+{
+ public Guid CustomArgument { get; set; }
+}
+
+file interface IUserRepository : IViewRepository
+{
+}
+
+file class UserRepositoryWithWrongConstructor : ViewRepository, IUserRepository
+{
+ public UserRepositoryWithWrongConstructor(IOptions> options, IOptions? defaultOptions) : base(options, defaultOptions)
+ {
+ }
+}
+
+file class UserRepositoryWithRightConstructor : ViewRepository, IUserRepository
+{
+ public UserRepositoryWithRightConstructor(IOptions options, IOptions? defaultOptions) : base(options, defaultOptions)
+ {
+ CustomArgument = options.Value.CustomArgument;
+ }
+
+ public Guid CustomArgument { get; }
+}
\ No newline at end of file