Tim Jones 5 месяцев назад
Родитель
Сommit
f1a74b389b

+ 5 - 4
RackPeek.Domain/Resources/Hardware/AccessPoints/AddAccessPointUseCase.cs

@@ -3,15 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.AccessPoints;
 
-public class AddAccessPointUseCase(IHardwareRepository repository) : IUseCase
+public class AddAccessPointUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new ConflictException($"Access point '{name}' already exists.");
+        
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var ap = new AccessPoint
         {

+ 4 - 4
RackPeek.Domain/Resources/Hardware/Desktops/AddDesktopUseCase.cs

@@ -3,16 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Desktops;
 
-public class AddDesktopUseCase(IHardwareRepository repository) : IUseCase
+public class AddDesktopUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new ConflictException($"Desktop '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var desktop = new Desktop
         {

+ 4 - 5
RackPeek.Domain/Resources/Hardware/Firewalls/AddFirewallUseCase.cs

@@ -3,17 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Firewalls;
 
-public class AddFirewallUseCase(IHardwareRepository repository) : IUseCase
+public class AddFirewallUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new NotFoundException($"Firewall '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var firewallResource = new Firewall
         {

+ 4 - 4
RackPeek.Domain/Resources/Hardware/Laptops/AddLaptopUseCase.cs

@@ -3,16 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Laptops;
 
-public class AddLaptopUseCase(IHardwareRepository repository) : IUseCase
+public class AddLaptopUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new InvalidOperationException($"Laptop '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var laptop = new Laptop
         {

+ 4 - 5
RackPeek.Domain/Resources/Hardware/Routers/AddRouterUseCase.cs

@@ -3,17 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Routers;
 
-public class AddRouterUseCase(IHardwareRepository repository) : IUseCase
+public class AddRouterUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new ConflictException($"Router '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var routerResource = new Router
         {

+ 4 - 5
RackPeek.Domain/Resources/Hardware/Servers/AddServerUseCase.cs

@@ -3,17 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Servers;
 
-public class AddServerUseCase(IHardwareRepository repository) : IUseCase
+public class AddServerUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new ConflictException($"Resource: '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var server = new Server
         {

+ 4 - 5
RackPeek.Domain/Resources/Hardware/Switches/AddSwitchUseCase.cs

@@ -3,17 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.Switches;
 
-public class AddSwitchUseCase(IHardwareRepository repository) : IUseCase
+public class AddSwitchUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new InvalidOperationException($"Switch '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var switchResource = new Switch
         {

+ 4 - 4
RackPeek.Domain/Resources/Hardware/UpsUnits/AddUpsUseCase.cs

@@ -3,16 +3,16 @@ using RackPeek.Domain.Resources.Hardware.Models;
 
 namespace RackPeek.Domain.Resources.Hardware.UpsUnits;
 
-public class AddUpsUseCase(IHardwareRepository repository) : IUseCase
+public class AddUpsUseCase(IHardwareRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.HardwareName(name);
         ThrowIfInvalid.ResourceName(name);
 
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new InvalidOperationException($"UPS '{name}' already exists.");
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var ups = new Ups
         {

+ 8 - 0
RackPeek.Domain/Resources/IResourceRepository.cs

@@ -0,0 +1,8 @@
+namespace RackPeek.Domain.Resources;
+
+public interface IResourceRepository
+{
+    public Task<string?> GetResourceKindAsync(string name);
+    public Task<bool> ResourceExistsAsync(string name);
+
+}

+ 5 - 5
RackPeek.Domain/Resources/Services/UseCases/AddServiceUseCase.cs

@@ -2,16 +2,16 @@ using RackPeek.Domain.Helpers;
 
 namespace RackPeek.Domain.Resources.Services.UseCases;
 
-public class AddServiceUseCase(IServiceRepository repository) : IUseCase
+public class AddServiceUseCase(IServiceRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.ServiceName(name);
         ThrowIfInvalid.ResourceName(name);
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new InvalidOperationException($"Service '{name}' already exists.");
+
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var service = new Service
         {

+ 5 - 5
RackPeek.Domain/Resources/SystemResources/UseCases/AddSystemUseCase.cs

@@ -2,16 +2,16 @@ using RackPeek.Domain.Helpers;
 
 namespace RackPeek.Domain.Resources.SystemResources.UseCases;
 
-public class AddSystemUseCase(ISystemRepository repository) : IUseCase
+public class AddSystemUseCase(ISystemRepository repository, IResourceRepository resourceRepo) : IUseCase
 {
     public async Task ExecuteAsync(string name)
     {
         name = Normalize.SystemName(name);
         ThrowIfInvalid.ResourceName(name);
-        // basic guard rails
-        var existing = await repository.GetByNameAsync(name);
-        if (existing != null)
-            throw new InvalidOperationException($"System '{name}' already exists.");
+
+        var existingResourceKind = await resourceRepo.GetResourceKindAsync(name);
+        if (!string.IsNullOrEmpty(existingResourceKind))
+            throw new ConflictException($"{existingResourceKind} resource '{name}' already exists.");
 
         var system = new SystemResource
         {

+ 3 - 1
RackPeek/CliBootstrap.cs

@@ -24,6 +24,7 @@ using RackPeek.Commands.Systems;
 using RackPeek.Commands.Ups;
 using RackPeek.Domain;
 using RackPeek.Domain.Helpers;
+using RackPeek.Domain.Resources;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Services;
 using RackPeek.Domain.Resources.SystemResources;
@@ -69,7 +70,8 @@ public static class CliBootstrap
         services.AddScoped<IHardwareRepository>(_ => new YamlHardwareRepository(collection));
         services.AddScoped<ISystemRepository>(_ => new YamlSystemRepository(collection));
         services.AddScoped<IServiceRepository>(_ => new YamlServiceRepository(collection));
-
+        services.AddScoped<IResourceRepository>(_ => new YamlResourceRepository(collection));
+        
         // Application
         services.AddUseCases();
         services.AddCommands();

+ 49 - 0
RackPeek/Yaml/YamlResourceRepository.cs

@@ -0,0 +1,49 @@
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.SystemResources;
+
+namespace RackPeek.Yaml;
+
+public class YamlResourceRepository(YamlResourceCollection resources) : IResourceRepository
+{
+    public Task<string?> GetResourceKindAsync(string name)
+    {
+        var hardware = resources.HardwareResources.FirstOrDefault(r => r.Name == name);
+        if (hardware != null)
+        {
+            return Task.FromResult<string?>(hardware.Kind);
+        }
+        var systemResource = resources.SystemResources.FirstOrDefault(r => r.Name == name);
+        if (systemResource != null)
+        {
+            return Task.FromResult<string?>(systemResource.Kind);
+        }
+        var service = resources.ServiceResources.FirstOrDefault(r => r.Name == name);
+        if (service != null)
+        {
+            return Task.FromResult<string?>(service.Kind);
+        }
+        
+        return Task.FromResult<string?>(null);
+    }
+
+    public Task<bool> ResourceExistsAsync(string name)
+    {
+        var hardware = resources.HardwareResources.FirstOrDefault(r => r.Name == name);
+        if (hardware != null)
+        {
+            return Task.FromResult(true);
+        }
+        var systemResource = resources.SystemResources.FirstOrDefault(r => r.Name == name);
+        if (systemResource != null)
+        {
+            return Task.FromResult(true);
+        }
+        var service = resources.ServiceResources.FirstOrDefault(r => r.Name == name);
+        if (service != null)
+        {
+            return Task.FromResult(true);
+        }
+        
+        return Task.FromResult(false);
+    }
+}

+ 7 - 6
Tests/HardwareResources/AccessPoints/AddAccessPointUseCaseTests.cs

@@ -12,10 +12,11 @@ public class AddAccessPointUseCaseTests
     public async Task ExecuteAsync_Adds_new_ap_when_not_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
         repo.GetByNameAsync("ap01").Returns((Hardware?)null);
 
-        var sut = new AddAccessPointUseCase(repo);
+        var sut = host.Get<AddAccessPointUseCase>();
 
         // Act
         await sut.ExecuteAsync("ap01");
@@ -30,10 +31,10 @@ public class AddAccessPointUseCaseTests
     public async Task ExecuteAsync_Throws_if_ap_already_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
-        repo.GetByNameAsync("ap01").Returns(new AccessPoint { Name = "ap01" });
+        var host = new UsecaseTestHost();
+        host.ResourceRepo.GetResourceKindAsync("ap01").Returns("Server");
 
-        var sut = new AddAccessPointUseCase(repo);
+        var sut = host.Get<AddAccessPointUseCase>();
 
         // Act
         var ex = await Assert.ThrowsAsync<ConflictException>(async () =>
@@ -41,6 +42,6 @@ public class AddAccessPointUseCaseTests
         );
 
         // Assert
-        await repo.DidNotReceive().AddAsync(Arg.Any<AccessPoint>());
+        await host.HardwareRepo.DidNotReceive().AddAsync(Arg.Any<AccessPoint>());
     }
 }

+ 8 - 6
Tests/HardwareResources/AddServerUseCaseTests.cs

@@ -12,10 +12,11 @@ public class AddServerUseCaseTests
     public async Task ExecuteAsync_Adds_new_server_when_not_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
         repo.GetByNameAsync("node01").Returns((Hardware?)null);
 
-        var sut = new AddServerUseCase(repo);
+        var sut = host.Get<AddServerUseCase>();
 
         // Act
         await sut.ExecuteAsync(
@@ -32,11 +33,12 @@ public class AddServerUseCaseTests
     public async Task ExecuteAsync_Throws_if_server_already_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
-        repo.GetByNameAsync("node01").Returns(new Server { Name = "node01" });
-
-        var sut = new AddServerUseCase(repo);
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
+        host.ResourceRepo.GetResourceKindAsync("node01").Returns("Server");
 
+        var sut = host.Get<AddServerUseCase>();
+        
         // Act
         var ex = await Assert.ThrowsAsync<ConflictException>(async () =>
             await sut.ExecuteAsync(

+ 0 - 31
Tests/HardwareResources/DeleteServerUseCaseTests.cs

@@ -1,41 +1,10 @@
-using Microsoft.Extensions.DependencyInjection;
 using NSubstitute;
 using RackPeek.Domain.Helpers;
-using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Servers;
-using RackPeek.Domain.Resources.Services;
-using RackPeek.Domain.Resources.SystemResources;
 
 namespace Tests.HardwareResources;
 
-public class UsecaseTestHost
-{
-    private readonly ServiceCollection _sc;
-
-    public UsecaseTestHost()
-    {
-        HardwareRepo = Substitute.For<IHardwareRepository>();
-        SystemRepo = Substitute.For<ISystemRepository>();
-        ServiceRepo = Substitute.For<IServiceRepository>();
-        _sc = new ServiceCollection();
-        _sc.AddSingleton<IHardwareRepository>(HardwareRepo);
-        _sc.AddSingleton<ISystemRepository>(SystemRepo);
-        _sc.AddSingleton<IServiceRepository>(ServiceRepo);
-    }
-
-    public IHardwareRepository HardwareRepo { get; set; }
-    public ISystemRepository SystemRepo { get; set; }
-    public IServiceRepository ServiceRepo { get; set; }
-
-    public T Get<T>() where T : notnull
-    {
-        _sc.AddSingleton(typeof(T));
-        var sp = _sc.BuildServiceProvider();
-        return sp.GetRequiredService<T>();
-    }
-}
-
 public class DeleteServerUseCaseTests
 {
     [Fact]

+ 8 - 7
Tests/HardwareResources/Desktops/AddDesktopUseCaseTests.cs

@@ -11,12 +11,13 @@ public class AddDesktopUseCaseTests
     [Fact]
     public async Task Adds_New_Desktop()
     {
-        var repo = Substitute.For<IHardwareRepository>();
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
         repo.GetByNameAsync("desk1").Returns((Hardware?)null);
 
-        var useCase = new AddDesktopUseCase(repo);
+        var sut = host.Get<AddDesktopUseCase>();
 
-        await useCase.ExecuteAsync("desk1");
+        await sut.ExecuteAsync("desk1");
 
         await repo.Received().AddAsync(Arg.Is<Desktop>(d => d.Name == "desk1"));
     }
@@ -24,11 +25,11 @@ public class AddDesktopUseCaseTests
     [Fact]
     public async Task Throws_If_Desktop_Exists()
     {
-        var repo = Substitute.For<IHardwareRepository>();
-        repo.GetByNameAsync("desk1").Returns(new Desktop { Name = "desk1" });
+        var host = new UsecaseTestHost();
+        host.ResourceRepo.GetResourceKindAsync("desk1").Returns("Server");
 
-        var useCase = new AddDesktopUseCase(repo);
+        var sut = host.Get<AddDesktopUseCase>();
 
-        await Assert.ThrowsAsync<ConflictException>(() => useCase.ExecuteAsync("desk1"));
+        await Assert.ThrowsAsync<ConflictException>(() => sut.ExecuteAsync("desk1"));
     }
 }

+ 9 - 8
Tests/HardwareResources/Switches/AddSwitchUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.Switches;
@@ -11,10 +12,11 @@ public class AddSwitchUseCaseTests
     public async Task ExecuteAsync_Adds_new_switch_when_not_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
         repo.GetByNameAsync("sw01").Returns((Hardware?)null);
 
-        var sut = new AddSwitchUseCase(repo);
+        var sut = host.Get<AddSwitchUseCase>();
 
         // Act
         await sut.ExecuteAsync(
@@ -31,20 +33,19 @@ public class AddSwitchUseCaseTests
     public async Task ExecuteAsync_Throws_if_switch_already_exists()
     {
         // Arrange
-        var repo = Substitute.For<IHardwareRepository>();
-        repo.GetByNameAsync("sw01").Returns(new Switch { Name = "sw01" });
+        var host = new UsecaseTestHost();
+        host.ResourceRepo.GetResourceKindAsync("sw01").Returns("Server");
 
-        var sut = new AddSwitchUseCase(repo);
+        var sut = host.Get<AddSwitchUseCase>();
 
         // Act
-        var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
+        var ex = await Assert.ThrowsAsync<ConflictException>(async () =>
             await sut.ExecuteAsync(
                 "sw01"
             )
         );
 
         // Assert
-        Assert.Equal("Switch 'sw01' already exists.", ex.Message);
-        await repo.DidNotReceive().AddAsync(Arg.Any<Switch>());
+        await host.HardwareRepo.DidNotReceive().AddAsync(Arg.Any<Switch>());
     }
 }

+ 10 - 8
Tests/HardwareResources/Ups/AddUpsUseCaseTests.cs

@@ -1,4 +1,5 @@
 using NSubstitute;
+using RackPeek.Domain.Helpers;
 using RackPeek.Domain.Resources.Hardware;
 using RackPeek.Domain.Resources.Hardware.Models;
 using RackPeek.Domain.Resources.Hardware.UpsUnits;
@@ -10,10 +11,11 @@ public class AddUpsUseCaseTests
     [Fact]
     public async Task ExecuteAsync_Adds_new_ups_when_not_exists()
     {
-        var repo = Substitute.For<IHardwareRepository>();
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
         repo.GetByNameAsync("ups01").Returns((Hardware?)null);
 
-        var sut = new AddUpsUseCase(repo);
+        var sut = host.Get<AddUpsUseCase>();
 
         await sut.ExecuteAsync("ups01");
 
@@ -25,16 +27,16 @@ public class AddUpsUseCaseTests
     [Fact]
     public async Task ExecuteAsync_Throws_if_ups_already_exists()
     {
-        var repo = Substitute.For<IHardwareRepository>();
-        repo.GetByNameAsync("ups01").Returns(new RackPeek.Domain.Resources.Hardware.Models.Ups { Name = "ups01" });
+        var host = new UsecaseTestHost();
+        var repo = host.HardwareRepo;
+        host.ResourceRepo.GetResourceKindAsync("ups01").Returns("Server");
 
-        var sut = new AddUpsUseCase(repo);
-
-        var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
+        var sut = host.Get<AddUpsUseCase>();
+        
+        var ex = await Assert.ThrowsAsync<ConflictException>(async () =>
             await sut.ExecuteAsync("ups01")
         );
 
-        Assert.Equal("UPS 'ups01' already exists.", ex.Message);
         await repo.DidNotReceive().AddAsync(Arg.Any<RackPeek.Domain.Resources.Hardware.Models.Ups>());
     }
 }

+ 39 - 0
Tests/HardwareResources/UsecaseTestHost.cs

@@ -0,0 +1,39 @@
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+using RackPeek.Domain.Resources;
+using RackPeek.Domain.Resources.Hardware;
+using RackPeek.Domain.Resources.Services;
+using RackPeek.Domain.Resources.SystemResources;
+
+namespace Tests.HardwareResources;
+
+public class UsecaseTestHost
+{
+    private readonly ServiceCollection _sc;
+
+    public UsecaseTestHost()
+    {
+        HardwareRepo = Substitute.For<IHardwareRepository>();
+        SystemRepo = Substitute.For<ISystemRepository>();
+        ServiceRepo = Substitute.For<IServiceRepository>();
+        ResourceRepo = Substitute.For<IResourceRepository>();
+        
+        _sc = new ServiceCollection();
+        _sc.AddSingleton<IHardwareRepository>(HardwareRepo);
+        _sc.AddSingleton<ISystemRepository>(SystemRepo);
+        _sc.AddSingleton<IServiceRepository>(ServiceRepo);
+        _sc.AddSingleton<IResourceRepository>(ResourceRepo);
+    }
+
+    public IHardwareRepository HardwareRepo { get; set; }
+    public ISystemRepository SystemRepo { get; set; }
+    public IServiceRepository ServiceRepo { get; set; }
+    
+    public IResourceRepository ResourceRepo { get; set; }
+    public T Get<T>() where T : notnull
+    {
+        _sc.AddSingleton(typeof(T));
+        var sp = _sc.BuildServiceProvider();
+        return sp.GetRequiredService<T>();
+    }
+}