diff --git a/SampleWebApiAspNetCore/Common/DependencyInjectionConfig.cs b/SampleWebApiAspNetCore/Common/DependencyInjectionConfig.cs
new file mode 100644
index 0000000..cb8a28e
--- /dev/null
+++ b/SampleWebApiAspNetCore/Common/DependencyInjectionConfig.cs
@@ -0,0 +1,38 @@
+using SampleWebApiAspNetCore.Common.Interface;
+
+namespace SampleWebApiAspNetCore.Common;
+
+internal static class DependencyInjectionConfig
+{
+ internal static IServiceCollection AddContracts(this IServiceCollection services)
+ {
+ services.RegisterImplementations(typeof(ITransientService), ServiceLifetime.Transient);
+ services.RegisterImplementations(typeof(IScopedService), ServiceLifetime.Scoped);
+ services.RegisterImplementations(typeof(ISingletonService), ServiceLifetime.Singleton);
+ return services;
+ }
+ private static IServiceCollection RegisterImplementations(this IServiceCollection services, Type interfaceType, ServiceLifetime lifetime)
+ {
+ var implementationTypes = AppDomain.CurrentDomain.GetAssemblies()
+ .SelectMany(assembly => assembly.GetTypes())
+ .Where(type => interfaceType.IsAssignableFrom(type) && type.IsClass && !type.IsAbstract)
+ .Select(type => new { Interface = type.GetInterfaces().FirstOrDefault(), Implementation = type })
+ .Where(type => type.Interface != null && interfaceType.IsAssignableFrom(type.Interface));
+
+ foreach (var implementationType in implementationTypes)
+ services.RegisterService(implementationType.Interface!, implementationType.Implementation, lifetime);
+
+ return services;
+ }
+
+ private static IServiceCollection RegisterService(this IServiceCollection services, Type interfaceType, Type implementationType, ServiceLifetime lifetime)
+ {
+ return lifetime switch
+ {
+ ServiceLifetime.Transient => services.AddTransient(interfaceType, implementationType),
+ ServiceLifetime.Scoped => services.AddScoped(interfaceType, implementationType),
+ ServiceLifetime.Singleton => services.AddSingleton(interfaceType, implementationType),
+ _ => throw new ArgumentException("Invalid lifetime specified", nameof(lifetime))
+ };
+ }
+}
diff --git a/SampleWebApiAspNetCore/Common/Interface/IScopedService.cs b/SampleWebApiAspNetCore/Common/Interface/IScopedService.cs
new file mode 100644
index 0000000..7d06580
--- /dev/null
+++ b/SampleWebApiAspNetCore/Common/Interface/IScopedService.cs
@@ -0,0 +1,12 @@
+namespace SampleWebApiAspNetCore.Common.Interface;
+
+///
+/// Interface for a scoped service in dependency injection.
+/// Scoped services are created once per request.
+///
+/// If an interface inherits this interface, it will be automatically registered
+/// by a common dependency injection configuration class.
+///
+public interface IScopedService
+{
+}
diff --git a/SampleWebApiAspNetCore/Common/Interface/ISingletonService.cs b/SampleWebApiAspNetCore/Common/Interface/ISingletonService.cs
new file mode 100644
index 0000000..eded058
--- /dev/null
+++ b/SampleWebApiAspNetCore/Common/Interface/ISingletonService.cs
@@ -0,0 +1,12 @@
+namespace SampleWebApiAspNetCore.Common.Interface;
+
+///
+/// Interface for a singleton service in dependency injection.
+/// Singleton services are created once and shared throughout the application.
+///
+/// If an interface inherits this interface, it will be automatically registered
+/// by a common dependency injection configuration class.
+///
+public interface ISingletonService
+{
+}
diff --git a/SampleWebApiAspNetCore/Common/Interface/ITransientService.cs b/SampleWebApiAspNetCore/Common/Interface/ITransientService.cs
new file mode 100644
index 0000000..df04e64
--- /dev/null
+++ b/SampleWebApiAspNetCore/Common/Interface/ITransientService.cs
@@ -0,0 +1,13 @@
+namespace SampleWebApiAspNetCore.Common.Interface;
+
+///
+/// Interface for a transient service in dependency injection.
+/// Transient services are created anew each time they are requested.
+///
+/// If an interface inherits this interface, it will be automatically registered
+/// by a common dependency injection configuration class.
+///
+public interface ITransientService
+{
+}
+
diff --git a/SampleWebApiAspNetCore/Program.cs b/SampleWebApiAspNetCore/Program.cs
index 9e890c6..87097de 100644
--- a/SampleWebApiAspNetCore/Program.cs
+++ b/SampleWebApiAspNetCore/Program.cs
@@ -1,4 +1,3 @@
-using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
@@ -6,6 +5,7 @@
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Serialization;
using SampleWebApiAspNetCore;
+using SampleWebApiAspNetCore.Common;
using SampleWebApiAspNetCore.Helpers;
using SampleWebApiAspNetCore.MappingProfiles;
using SampleWebApiAspNetCore.Repositories;
@@ -18,7 +18,7 @@
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
- options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
+ options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
@@ -26,8 +26,10 @@
builder.Services.AddCustomCors("AllowAllOrigins");
-builder.Services.AddSingleton();
-builder.Services.AddScoped();
+//All services of the application will be configured and registered using a generic approach by AddContracts.
+builder.Services.AddContracts();
+//builder.Services.AddSingleton();
+//builder.Services.AddScoped();
builder.Services.AddScoped(typeof(ILinkService<>), typeof(LinkService<>));
builder.Services.AddTransient, ConfigureSwaggerOptions>();
@@ -63,7 +65,7 @@
});
app.SeedData();
-}
+}
else
{
app.AddProductionExceptionHandling(loggerFactory);
diff --git a/SampleWebApiAspNetCore/Repositories/IFoodRepository.cs b/SampleWebApiAspNetCore/Repositories/IFoodRepository.cs
index 26574b2..db76664 100644
--- a/SampleWebApiAspNetCore/Repositories/IFoodRepository.cs
+++ b/SampleWebApiAspNetCore/Repositories/IFoodRepository.cs
@@ -1,9 +1,10 @@
-using SampleWebApiAspNetCore.Entities;
+using SampleWebApiAspNetCore.Common.Interface;
+using SampleWebApiAspNetCore.Entities;
using SampleWebApiAspNetCore.Models;
namespace SampleWebApiAspNetCore.Repositories
{
- public interface IFoodRepository
+ public interface IFoodRepository : IScopedService
{
FoodEntity GetSingle(int id);
void Add(FoodEntity item);
diff --git a/SampleWebApiAspNetCore/Services/ISeedDataService.cs b/SampleWebApiAspNetCore/Services/ISeedDataService.cs
index c649c8e..a8e5874 100644
--- a/SampleWebApiAspNetCore/Services/ISeedDataService.cs
+++ b/SampleWebApiAspNetCore/Services/ISeedDataService.cs
@@ -1,8 +1,9 @@
-using SampleWebApiAspNetCore.Repositories;
+using SampleWebApiAspNetCore.Common.Interface;
+using SampleWebApiAspNetCore.Repositories;
namespace SampleWebApiAspNetCore.Services
{
- public interface ISeedDataService
+ public interface ISeedDataService : ISingletonService
{
void Initialize(FoodDbContext context);
}