diff --git a/README.md b/README.md index bd56820..1e4bc53 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ SPAL.Core should provide the following features: ![Current Engineering Overview](https://github.com/The-Standard-Organization/STX.SPAL.Core/blob/main/STX.SPAL.Core/Resources/Diagrams/spal-diagram-ovtab-05302024.png) -![Current Engineering Status](https://github.com/The-Standard-Organization/STX.SPAL.Core/blob/main/STX.SPAL.Core/Resources/Diagrams/spal-diagram-coretab-06072024.png) +![Current Engineering Status](https://github.com/The-Standard-Organization/STX.SPAL.Core/blob/main/STX.SPAL.Core/Resources/Diagrams/spal-diagram-coretab-05102024.png) ## Standard-Compliance This library was built according to The Standard. The library follows engineering principles, patterns and tooling as recommended by The Standard. diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Exceptions.GetAssembly.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Exceptions.GetAssembly.cs index 95e8edc..7115dac 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Exceptions.GetAssembly.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Exceptions.GetAssembly.cs @@ -45,7 +45,7 @@ private void ShouldThrowDependencyExceptionOnLoadAssemblyIfExternalExceptionOccu Assert.Throws( getAssemblyFunction); - //then + // then actualAssemblyDependencyException.Should().BeEquivalentTo( expectedAssemblyDependencyException); @@ -90,7 +90,7 @@ private void ShouldThrowValidationDependencyExceptionOnLoadAssemblyIfExternalExc Assert.Throws( getAssemblyFunction); - //then + // then actualAssemblyValidationDependencyException.Should().BeEquivalentTo( expectedAssemblyValidationDependencyException); @@ -135,7 +135,7 @@ private void ShouldThrowServiceExceptionOnLoadAssemblyIfExceptionOccurs( Assert.Throws( getAssemblyFunction); - //then + // then actualAssemblyServiceException.Should().BeEquivalentTo( expectedAssemblyServiceException); diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetApplicationPathsAssemblies.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetApplicationPathsAssemblies.cs index 4ed031b..9ecabd1 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetApplicationPathsAssemblies.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetApplicationPathsAssemblies.cs @@ -2,7 +2,6 @@ // Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers // ---------------------------------------------------------------------------------- -using System.Threading.Tasks; using FluentAssertions; using Moq; @@ -31,7 +30,7 @@ private void ShouldGetApplicationPathAssemblies() string[] actualApplicationPathsAssemblies = this.assemblyService.GetApplicationPathsAssemblies(); - //then + // then actualApplicationPathsAssemblies.Should() .BeEquivalentTo(expectedApplicationPathsAssemblies); diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetAssembly.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetAssembly.cs index 0c51fd8..bb216ab 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetAssembly.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetAssembly.cs @@ -31,7 +31,7 @@ private void ShouldGetAssembly() Assembly actualAssembly = this.assemblyService.GetAssembly(inputPathAssembly); - //then + // then actualAssembly.Should().BeSameAs(expectedAssembly); this.assemblyBroker.Verify( diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Validations.GetAssembly.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Validations.GetAssembly.cs index d410865..fea66b6 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Validations.GetAssembly.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Validations.GetAssembly.cs @@ -56,7 +56,7 @@ private void ShouldThrowValidationExceptionIfInvalidAssemblyPath( Assert.Throws( getAssemblyFunction); - //then + // then actualAssemblyValidationException.Should().BeEquivalentTo( expectedAssemblyValidationException); diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Exceptions.RegisterServiceDescriptor.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Exceptions.RegisterServiceDescriptor.cs index fcbc22f..20a4828 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Exceptions.RegisterServiceDescriptor.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Exceptions.RegisterServiceDescriptor.cs @@ -30,7 +30,7 @@ private void ShouldThrowValidationDependencyExceptionOnRegisterServiceDescriptor var expectedServiceCollectionValidationDependencyException = new DependencyInjectionValidationDependencyException( - message: "Service collection validation dependency error occurred, contact support.", + message: "Dependency Injection validation dependency error occurred, contact support.", innerException: addServiceDescriptorException); this.dependencyInjectionBroker @@ -57,7 +57,7 @@ private void ShouldThrowValidationDependencyExceptionOnRegisterServiceDescriptor Assert.Throws( registerServiceDescriptorFunction); - //then + // then actualServiceCollectionValidationDependencyException.Should().BeEquivalentTo( expectedServiceCollectionValidationDependencyException); @@ -88,7 +88,7 @@ private void ShouldThrowServiceExceptionOnRegisterServiceDescriptorIfExceptionOc var expectedServiceCollectionServiceException = new DependencyInjectionServiceException( - message: "ServiceCollection service error occurred, contact support.", + message: "Dependency Injection service error occurred, contact support.", innerException: assemblyLoadException); this.dependencyInjectionBroker @@ -115,7 +115,7 @@ private void ShouldThrowServiceExceptionOnRegisterServiceDescriptorIfExceptionOc Assert.Throws( registerServiceDescriptorFunction); - //then + // then actualServiceCollectionServiceException.Should().BeEquivalentTo( expectedServiceCollectionServiceException); diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.BuildServiceProvider.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.BuildServiceProvider.cs new file mode 100644 index 0000000..365aaaf --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.BuildServiceProvider.cs @@ -0,0 +1,70 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.DependenciesInjections +{ + public partial class DependencyInjectionServiceTests + { + [Fact] + private void ShouldBuildServiceProvider() + { + // given + dynamic randomProperties = CreateRandomProperties(); + dynamic inputProperties = randomProperties; + + ServiceDescriptor randomServiceDescriptor = randomProperties.ServiceDescriptor; + ServiceDescriptor inputServiceDescriptor = randomServiceDescriptor; + ServiceDescriptor expectedServiceDescriptor = inputServiceDescriptor; + + DependencyInjection inputDependencyInjection = inputProperties.DependencyInjection; + inputDependencyInjection.ServiceCollection.Add(inputServiceDescriptor); + + DependencyInjection expectedDependencyInjection = + new DependencyInjection + { + ServiceCollection = inputDependencyInjection.ServiceCollection, + ServiceProvider = inputDependencyInjection.ServiceCollection.BuildServiceProvider() + }; + + DependencyInjection returnedDependencyInjection = expectedDependencyInjection; + + this.dependencyInjectionBroker + .Setup(broker => + broker.BuildServiceProvider( + It.Is(actualServiceCollection => + SameServiceCollectionAs( + actualServiceCollection, + expectedDependencyInjection.ServiceCollection) + .Compile() + .Invoke(inputDependencyInjection.ServiceCollection)))) + .Returns(returnedDependencyInjection.ServiceProvider); + + // when + DependencyInjection actualDependencyInjection = + this.dependencyInjectionService.BuildServiceProvider( + inputProperties.DependencyInjection); + + // then + actualDependencyInjection.Should().BeEquivalentTo(expectedDependencyInjection); + + this.dependencyInjectionBroker.Verify( + broker => + broker.BuildServiceProvider( + It.Is(actualServiceCollection => + SameServiceCollectionAs( + actualServiceCollection, + expectedDependencyInjection.ServiceCollection) + .Compile() + .Invoke(actualDependencyInjection.ServiceCollection))), + Times.Once); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + } +} diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.GetService.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.GetService.cs new file mode 100644 index 0000000..f09d204 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.GetService.cs @@ -0,0 +1,149 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using FluentAssertions; +using Force.DeepCloner; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using STX.SPAL.Abstractions; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.DependenciesInjections +{ + public partial class DependencyInjectionServiceTests + { + [Fact] + private void ShouldGetService() + { + // given + dynamic randomProperties = CreateRandomProperties(); + dynamic inputProperties = randomProperties; + + ServiceDescriptor randomServiceDescriptor = randomProperties.ServiceDescriptor; + ServiceDescriptor inputServiceDescriptor = randomServiceDescriptor; + ServiceDescriptor expectedServiceDescriptor = inputServiceDescriptor; + + IServiceCollection inputServiceCollection = inputProperties.DependencyInjection.ServiceCollection; + inputServiceCollection.Add(inputServiceDescriptor); + + DependencyInjection inputDependencyInjection = + new DependencyInjection + { + ServiceCollection = inputServiceCollection, + ServiceProvider = inputServiceCollection.BuildServiceProvider() + }; + + Type implementationType = randomProperties.ImplementationType; + + ISPALBase returnedService = + Activator.CreateInstance(implementationType) as ISPALBase; + + ISPALBase expectedService = returnedService; + + DependencyInjection expectedDependencyInjection = inputDependencyInjection.DeepClone(); + DependencyInjection returnedDependencyInjection = expectedDependencyInjection; + + this.dependencyInjectionBroker + .Setup(broker => + broker.GetService( + It.Is(actualServiceProvider => + SameServiceProviderAs( + actualServiceProvider, + expectedDependencyInjection.ServiceProvider) + .Compile() + .Invoke(inputDependencyInjection.ServiceProvider)))) + .Returns(returnedService); + + // when + ISPALBase actualService = + this.dependencyInjectionService.GetService( + inputDependencyInjection); + + //then + actualService.Should().BeEquivalentTo(expectedService); + + this.dependencyInjectionBroker.Verify( + broker => + broker.GetService( + It.Is(actualServiceProvider => + SameServiceProviderAs( + actualServiceProvider, + expectedDependencyInjection.ServiceProvider) + .Compile() + .Invoke(inputDependencyInjection.ServiceProvider))), + Times.Once); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + + [Fact] + private void ShouldGetServiceWithSpalId() + { + // given + dynamic randomProperties = CreateRandomProperties(); + dynamic inputProperties = randomProperties; + + ServiceDescriptor randomServiceDescriptor = randomProperties.ServiceDescriptorWithSpalId; + ServiceDescriptor inputServiceDescriptor = randomServiceDescriptor; + ServiceDescriptor expectedServiceDescriptor = inputServiceDescriptor; + + + IServiceCollection inputServiceCollection = inputProperties.DependencyInjection.ServiceCollection; + inputServiceCollection.Add(inputServiceDescriptor); + + DependencyInjection inputDependencyInjection = + new DependencyInjection + { + ServiceCollection = inputServiceCollection, + ServiceProvider = inputServiceCollection.BuildServiceProvider() + }; + + Type implementationType = randomProperties.ImplementationType; + + ISPALBase returnedService = + Activator.CreateInstance(implementationType) as ISPALBase; + + ISPALBase expectedService = returnedService; + + DependencyInjection expectedDependencyInjection = inputDependencyInjection.DeepClone(); + DependencyInjection returnedDependencyInjection = expectedDependencyInjection; + + this.dependencyInjectionBroker + .Setup(broker => + broker.GetService( + It.Is(actualServiceProvider => + SameServiceProviderAs( + actualServiceProvider, + expectedDependencyInjection.ServiceProvider) + .Compile() + .Invoke(inputDependencyInjection.ServiceProvider)), + It.IsAny())) + .Returns(returnedService); + + // when + ISPALBase actualService = + this.dependencyInjectionService.GetService( + inputDependencyInjection, + inputProperties.SpalId); + + // then + actualService.Should().BeEquivalentTo(expectedService); + + this.dependencyInjectionBroker.Verify( + broker => + broker.GetService( + It.Is(actualServiceProvider => + SameServiceProviderAs( + actualServiceProvider, + expectedDependencyInjection.ServiceProvider) + .Compile() + .Invoke(inputDependencyInjection.ServiceProvider)), + It.IsAny()), + Times.Once); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + } +} diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.RegisterServiceDescriptor.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.RegisterServiceDescriptor.cs index 7b381e2..da7e27a 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.RegisterServiceDescriptor.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Logic.RegisterServiceDescriptor.cs @@ -50,7 +50,7 @@ private void ShouldRegisterServiceDescriptor() inputProperties.ImplementationType, inputProperties.ServiceLifeTime); - //then + // then actualDependencyInjection.Should().BeEquivalentTo(expectedDependencyInjection); this.dependencyInjectionBroker.Verify( @@ -107,7 +107,7 @@ private void ShouldRegisterServiceDescriptorWithSpalId() inputProperties.ImplementationType, inputProperties.ServiceLifeTime); - //then + // then actualDependencyInjection.Should().BeEquivalentTo(expectedDependencyInjection); this.dependencyInjectionBroker.Verify( diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.BuildServiceProvider.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.BuildServiceProvider.cs new file mode 100644 index 0000000..c458835 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.BuildServiceProvider.cs @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions; +using Xeptions; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.DependenciesInjections +{ + public partial class DependencyInjectionServiceTests + { + [Theory] + [MemberData(nameof(BuildServiceProviderValidationExceptions))] + private void ShouldThrowValidationExceptionIfInvalidParametersOnBuildServiceProvider( + DependencyInjection someDependencyInjection, + Xeption exception) + { + // given + var expectedDependencyInjectionValidationException = + new DependencyInjectionValidationException( + message: "Dependency Injection validation error occurred, fix errors and try again.", + innerException: exception); + + this.dependencyInjectionBroker + .Setup(broker => + broker.BuildServiceProvider( + It.IsAny())); + + // when + Func buildServiceProviderFunction = () => + this.dependencyInjectionService.BuildServiceProvider( + someDependencyInjection); + + DependencyInjectionValidationException actualDependencyInjectionValidationException = + Assert.Throws( + buildServiceProviderFunction); + + // then + actualDependencyInjectionValidationException.Should().BeEquivalentTo( + expectedDependencyInjectionValidationException); + + this.dependencyInjectionBroker + .Verify(broker => + broker.BuildServiceProvider( + It.IsAny()), + Times.Never); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + } +} diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.GetService.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.GetService.cs new file mode 100644 index 0000000..519b8b1 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.GetService.cs @@ -0,0 +1,99 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using FluentAssertions; +using Moq; +using STX.SPAL.Abstractions; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions; +using Xeptions; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.DependenciesInjections +{ + public partial class DependencyInjectionServiceTests + { + [Theory] + [MemberData(nameof(GetServiceValidationExceptions))] + private void ShouldThrowValidationExceptionIfInvalidParametersOnGetService( + DependencyInjection someDependencyInjection, + Xeption exception) + { + // given + var expectedDependencyInjectionValidationException = + new DependencyInjectionValidationException( + message: "Dependency Injection validation error occurred, fix errors and try again.", + innerException: exception); + + this.dependencyInjectionBroker + .Setup(broker => + broker.GetService( + It.IsAny())); + + // when + Func getServiceFunction = () => + this.dependencyInjectionService.GetService( + someDependencyInjection); + + DependencyInjectionValidationException actualDependencyInjectionValidationException = + Assert.Throws( + getServiceFunction); + + // then + actualDependencyInjectionValidationException.Should().BeEquivalentTo( + expectedDependencyInjectionValidationException); + + this.dependencyInjectionBroker + .Verify(broker => + broker.GetService( + It.IsAny()), + Times.Never); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + + [Theory] + [MemberData(nameof(GetServiceWithSpalValidationExceptions))] + private void ShouldThrowValidationExceptionIfInvalidParametersOnGetServiceWithSpal( + DependencyInjection someDependencyInjection, + string someSpalId, + Xeption exception) + { + // given + var expectedDependencyInjectionValidationException = + new DependencyInjectionValidationException( + message: "Dependency Injection validation error occurred, fix errors and try again.", + innerException: exception); + + this.dependencyInjectionBroker + .Setup(broker => + broker.GetService( + It.IsAny(), + It.IsAny())); + + // when + Func getServiceFunction = () => + this.dependencyInjectionService.GetService( + someDependencyInjection, + someSpalId); + + DependencyInjectionValidationException actualDependencyInjectionValidationException = + Assert.Throws( + getServiceFunction); + + // then + actualDependencyInjectionValidationException.Should().BeEquivalentTo( + expectedDependencyInjectionValidationException); + + this.dependencyInjectionBroker + .Verify(broker => + broker.GetService( + It.IsAny(), + It.IsAny()), + Times.Never); + + this.dependencyInjectionBroker.VerifyNoOtherCalls(); + } + } +} diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.RegisterServiceDescriptor.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.RegisterServiceDescriptor.cs index 70b3635..408a74e 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.RegisterServiceDescriptor.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.Validations.RegisterServiceDescriptor.cs @@ -17,17 +17,15 @@ public partial class DependencyInjectionServiceTests [Theory] [MemberData(nameof(RegisterServiceDescriptorValidationExceptions))] private void ShouldThrowValidationExceptionIfInvalidParameters( + DependencyInjection someDependencyInjection, Type spalInterfaceType, Type implementationType, Xeption exception) { - dynamic randomProperties = CreateRandomProperties(); - DependencyInjection someDependencyInjection = randomProperties.DependencyInjection; - // given var expectedServiceCollectionValidationException = new DependencyInjectionValidationException( - message: "Service Collection validation error occurred, fix errors and try again.", + message: "Dependency Injection validation error occurred, fix errors and try again.", innerException: exception); this.dependencyInjectionBroker @@ -48,7 +46,7 @@ private void ShouldThrowValidationExceptionIfInvalidParameters( Assert.Throws( registerServiceDescriptorFunction); - //then + // then actualServiceCollectionValidationException.Should().BeEquivalentTo( expectedServiceCollectionValidationException); @@ -65,18 +63,16 @@ private void ShouldThrowValidationExceptionIfInvalidParameters( [Theory] [MemberData(nameof(RegisterServiceDescriptorWithSpalIdValidationExceptions))] private void ShouldThrowValidationExceptionIfInvalidParametersWhenUsingSpalId( + DependencyInjection someDependencyInjection, Type spalInterfaceType, string spalId, Type implementationType, Xeption exception) { - dynamic randomProperties = CreateRandomProperties(); - DependencyInjection someDependencyInjection = randomProperties.DependencyInjection; - // given var expectedServiceCollectionValidationException = new DependencyInjectionValidationException( - message: "Service Collection validation error occurred, fix errors and try again.", + message: "Dependency Injection validation error occurred, fix errors and try again.", innerException: exception); this.dependencyInjectionBroker @@ -98,7 +94,7 @@ private void ShouldThrowValidationExceptionIfInvalidParametersWhenUsingSpalId( Assert.Throws( registerServiceDescriptorFunction); - //then + // then actualServiceCollectionValidationException.Should().BeEquivalentTo( expectedServiceCollectionValidationException); diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.cs index 6a7b772..37296ec 100644 --- a/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.cs +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/DependenciesInjections/DependencyInjectionServiceTests.cs @@ -29,7 +29,9 @@ public partial class DependencyInjectionServiceTests public DependencyInjectionServiceTests() { - this.dependencyInjectionBroker = new Mock(); + this.dependencyInjectionBroker = + new Mock(); + this.compareLogic = new CompareLogic(); this.dependencyInjectionService = @@ -56,38 +58,75 @@ private static AssemblyBuilder CreateRandomAssembly() private static Type CreateRandomSpalInterfaceType() { + Type iSpalBaseType = typeof(ISPALBase); + AssemblyBuilder spalAssembly = CreateRandomAssembly(); string assemblyName = spalAssembly.GetName().Name; - ModuleBuilder moduleBuilder = spalAssembly.DefineDynamicModule(assemblyName); - - TypeBuilder typeBuilder = moduleBuilder.DefineType( - name: GetRandomString(), - attr: TypeAttributes.Public, - parent: null, - interfaces: new Type[] - { - typeof(ISPALBase) - }); - - return typeBuilder; + ModuleBuilder moduleBuilder = + spalAssembly.DefineDynamicModule(assemblyName); + + TypeBuilder typeBuilder = + moduleBuilder.DefineType( + name: GetRandomString(), + attr: TypeAttributes.Public + | TypeAttributes.Interface + | TypeAttributes.Abstract, + parent: null, + interfaces: new Type[] + { + iSpalBaseType + }); + + return typeBuilder.CreateType(); } private static Type CreateRandomImplementationType() { + Type iSpalBaseType = typeof(ISPALBase); + AssemblyBuilder spalAssembly = CreateRandomAssembly(); string assemblyName = spalAssembly.GetName().Name; - ModuleBuilder moduleBuilder = spalAssembly.DefineDynamicModule(assemblyName); - - TypeBuilder typeBuilder = moduleBuilder.DefineType( - name: GetRandomString(), - attr: TypeAttributes.Public, - parent: null, - interfaces: new Type[] - { - typeof(ISPALBase) - }); - - return typeBuilder; + ModuleBuilder moduleBuilder = + spalAssembly.DefineDynamicModule(assemblyName); + + TypeBuilder typeBuilder = + moduleBuilder.DefineType( + name: GetRandomString(), + attr: + TypeAttributes.Public + | TypeAttributes.Class); + + typeBuilder.AddInterfaceImplementation(iSpalBaseType); + + MethodInfo methodInfoGetSPALId = + iSpalBaseType + .GetMethod(nameof(ISPALBase.GetSPALId)); + + MethodBuilder getSPALIDMethodBuilder = + typeBuilder + .DefineMethod( + name: nameof(ISPALBase.GetSPALId), + attributes: + MethodAttributes.Public + | MethodAttributes.Final + | MethodAttributes.HideBySig + | MethodAttributes.NewSlot + | MethodAttributes.Virtual, + + returnType: typeof(string), + parameterTypes: Type.EmptyTypes); + + ILGenerator ilGenerator = + getSPALIDMethodBuilder.GetILGenerator(); + + ilGenerator.Emit(OpCodes.Ldstr, "Hello SPAL ID"); + ilGenerator.Emit(OpCodes.Ret); + + typeBuilder.DefineMethodOverride( + getSPALIDMethodBuilder, + iSpalBaseType.GetMethod(nameof(ISPALBase.GetSPALId))); + + return typeBuilder.CreateType(); } private static ServiceLifetime CreateRandomServiceLifeTime() @@ -141,10 +180,47 @@ private Expression> SameServiceDescriptorAs( ServiceDescriptor expectedServiceDescriptor) { return actualServiceDescriptor => - this.compareLogic.Compare( - expectedServiceDescriptor, - actualServiceDescriptor) - .AreEqual; + this.compareLogic + .Compare( + expectedServiceDescriptor, + actualServiceDescriptor) + .AreEqual; + } + + private Expression> SameServiceCollectionAs( + IServiceCollection actualServiceCollection, + IServiceCollection expectedServiceCollection) + { + return actualServiceCollection => + this.compareLogic + .Compare( + expectedServiceCollection, + actualServiceCollection) + .AreEqual; + } + + private Expression> SameServiceProviderAs( + IServiceProvider actualServiceProvider, + IServiceProvider expectedServiceProvider) + { + return actualServiceProvider => + this.compareLogic + .Compare( + expectedServiceProvider, + actualServiceProvider) + .AreEqual; + } + + private Expression> SameDependencyInjectionAs( + DependencyInjection actualDependencyInjection, + DependencyInjection expectedDependencyInjection) + { + return actualDependencyInjection => + this.compareLogic + .Compare( + expectedDependencyInjection, + actualDependencyInjection) + .AreEqual; } private static Xeption CreateInvalidServiceDescriptorParameterException( @@ -168,11 +244,89 @@ private static Xeption CreateInvalidServiceDescriptorParameterException( return invalidServiceDescriptorParameterException; } - public static TheoryData RegisterServiceDescriptorValidationExceptions() + private static Xeption CreateInvalidServiceCollectionParameterException( + IDictionary parameters) + { + var invalidServiceCollectionParameterException = + new InvalidServiceCollectionParameterException( + message: "Invalid service collection parameter error occurred, fix errors and try again."); + + parameters + .Select(parameter => + { + invalidServiceCollectionParameterException.UpsertDataList( + key: parameter.Key, + value: parameter.Value); + + return invalidServiceCollectionParameterException; + }) + .ToArray(); + + return invalidServiceCollectionParameterException; + } + + private static Xeption CreateInvalidDependencyInjectionParameterException( + IDictionary parameters) + { + var invalidDependencyInjectionParameterException = + new InvalidDependencyInjectionParameterException( + message: "Invalid dependency injection parameter error occurred, fix errors and try again."); + + parameters + .Select(parameter => + { + invalidDependencyInjectionParameterException.UpsertDataList( + key: parameter.Key, + value: parameter.Value); + + return invalidDependencyInjectionParameterException; + }) + .ToArray(); + + return invalidDependencyInjectionParameterException; + } + + private static Xeption CreateInvalidServiceProviderParameterException( + IDictionary parameters) { - return new TheoryData + var invalidServiceProviderParameterException = + new InvalidServiceProviderParameterException( + message: "Invalid service provider parameter error occurred, fix errors and try again."); + + parameters + .Select(parameter => + { + invalidServiceProviderParameterException.UpsertDataList( + key: parameter.Key, + value: parameter.Value); + + return invalidServiceProviderParameterException; + }) + .ToArray(); + + return invalidServiceProviderParameterException; + } + + public static TheoryData RegisterServiceDescriptorValidationExceptions() + { + dynamic randomProperties = CreateRandomProperties(); + DependencyInjection someDependencyInjection = randomProperties.DependencyInjection; + + return new TheoryData { { + null, + null, + null, + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + { nameof(DependencyInjection), "object is required" } + }) + }, + + { + someDependencyInjection, CreateRandomSpalInterfaceType(), null, CreateInvalidServiceDescriptorParameterException( @@ -183,6 +337,7 @@ public static TheoryData RegisterServiceDescriptorValidatio }, { + someDependencyInjection, null, CreateRandomImplementationType(), CreateInvalidServiceDescriptorParameterException( @@ -193,6 +348,7 @@ public static TheoryData RegisterServiceDescriptorValidatio }, { + someDependencyInjection, null, null, CreateInvalidServiceDescriptorParameterException( @@ -205,11 +361,27 @@ public static TheoryData RegisterServiceDescriptorValidatio }; } - public static TheoryData RegisterServiceDescriptorWithSpalIdValidationExceptions() + public static TheoryData RegisterServiceDescriptorWithSpalIdValidationExceptions() { - return new TheoryData + dynamic randomProperties = CreateRandomProperties(); + DependencyInjection someDependencyInjection = randomProperties.DependencyInjection; + + return new TheoryData { { + null, + null, + null, + null, + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + { nameof(DependencyInjection), "object is required" } + }) + }, + + { + someDependencyInjection, CreateRandomSpalInterfaceType(), GetRandomString(), null, @@ -221,6 +393,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, GetRandomString(), CreateRandomImplementationType(), @@ -232,6 +405,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, GetRandomString(), null, @@ -244,6 +418,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, CreateRandomSpalInterfaceType(), null, null, @@ -256,6 +431,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, null, CreateRandomImplementationType(), @@ -268,6 +444,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, null, null, @@ -281,6 +458,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, CreateRandomSpalInterfaceType(), "", null, @@ -293,6 +471,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, "", CreateRandomImplementationType(), @@ -305,6 +484,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, "", null, @@ -318,6 +498,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, CreateRandomSpalInterfaceType(), " ", null, @@ -330,6 +511,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, " ", CreateRandomImplementationType(), @@ -342,6 +524,7 @@ public static TheoryData RegisterServiceDescriptorW }, { + someDependencyInjection, null, " ", null, @@ -371,5 +554,129 @@ public static TheoryData RegisterServiceDescriptorServiceExceptions() new Exception() }; } + + public static TheoryData BuildServiceProviderValidationExceptions() + { + return new TheoryData + { + { + null, + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + {nameof(DependencyInjection), "object is required" } + }) + }, + + { + new DependencyInjection(), + CreateInvalidServiceCollectionParameterException( + new Dictionary + { + {nameof(ServiceCollection), "object is required" } + }) + }, + }; + } + + public static TheoryData GetServiceValidationExceptions() + { + return new TheoryData + { + { + null, + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + {nameof(DependencyInjection), "object is required" } + }) + }, + + { + new DependencyInjection(), + CreateInvalidServiceProviderParameterException( + new Dictionary + { + {nameof(ServiceProvider), "object is required" } + }) + }, + }; + } + + public static TheoryData GetServiceWithSpalValidationExceptions() + { + return new TheoryData + { + { + null, + null, + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + {nameof(DependencyInjection), "object is required" } + }) + }, + + { + new DependencyInjection(), + null, + CreateInvalidServiceProviderParameterException( + new Dictionary + { + {nameof(ServiceProvider), "object is required" }, + {"spalId", "Value is required" } + }) + }, + + { + new DependencyInjection + { + ServiceCollection = new ServiceCollection(), + ServiceProvider = new ServiceCollection().BuildServiceProvider() + }, + null, + CreateInvalidServiceProviderParameterException( + new Dictionary + { + {"spalId", "Value is required" } + }) + }, + + { + null, + " ", + CreateInvalidDependencyInjectionParameterException( + new Dictionary + { + {nameof(DependencyInjection), "object is required" } + }) + }, + + { + new DependencyInjection(), + " ", + CreateInvalidServiceProviderParameterException( + new Dictionary + { + {nameof(ServiceProvider), "object is required" }, + {"spalId", "Value is required" } + }) + }, + + { + new DependencyInjection + { + ServiceCollection = new ServiceCollection(), + ServiceProvider = new ServiceCollection().BuildServiceProvider() + }, + " ", + CreateInvalidServiceProviderParameterException( + new Dictionary + { + {"spalId", "Value is required" } + }) + }, + }; + } } } diff --git a/STX.SPAL.Core/Brokers/DependenciesInjections/DependencyInjectionBroker.ServiceProvider.cs b/STX.SPAL.Core/Brokers/DependenciesInjections/DependencyInjectionBroker.ServiceProvider.cs index 802d28b..564da5b 100644 --- a/STX.SPAL.Core/Brokers/DependenciesInjections/DependencyInjectionBroker.ServiceProvider.cs +++ b/STX.SPAL.Core/Brokers/DependenciesInjections/DependencyInjectionBroker.ServiceProvider.cs @@ -12,10 +12,10 @@ internal partial class DependencyInjectionBroker public IServiceProvider BuildServiceProvider(IServiceCollection serviceCollection) => serviceCollection.BuildServiceProvider(); - public T ResolveImplementation(ServiceProvider serviceProvider) => + public T GetService(IServiceProvider serviceProvider) => serviceProvider.GetRequiredService(); - public T ResolveImplementation(ServiceProvider serviceProvider, string spalId) => + public T GetService(IServiceProvider serviceProvider, string spalId) => serviceProvider.GetRequiredKeyedService(spalId); } } diff --git a/STX.SPAL.Core/Brokers/DependenciesInjections/IDependencyInjectionBroker.ServiceProvider.cs b/STX.SPAL.Core/Brokers/DependenciesInjections/IDependencyInjectionBroker.ServiceProvider.cs index 90f92f8..d3bf4e9 100644 --- a/STX.SPAL.Core/Brokers/DependenciesInjections/IDependencyInjectionBroker.ServiceProvider.cs +++ b/STX.SPAL.Core/Brokers/DependenciesInjections/IDependencyInjectionBroker.ServiceProvider.cs @@ -10,7 +10,7 @@ namespace STX.SPAL.Core.Brokers.DependenciesInjections internal partial interface IDependencyInjectionBroker { IServiceProvider BuildServiceProvider(IServiceCollection serviceCollection); - T ResolveImplementation(ServiceProvider serviceProvider); - T ResolveImplementation(ServiceProvider serviceProvider, string spalId); + T GetService(IServiceProvider serviceProvider); + T GetService(IServiceProvider serviceProvider, string spalId); } } diff --git a/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/DependencyInjection.cs b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/DependencyInjection.cs index 1a0bedb..03d00d8 100644 --- a/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/DependencyInjection.cs +++ b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/DependencyInjection.cs @@ -7,7 +7,7 @@ namespace STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections { - internal class DependencyInjection + public class DependencyInjection { public IServiceCollection ServiceCollection { get; init; } public IServiceProvider ServiceProvider { get; init; } diff --git a/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidDependencyInjectionParameterException.cs b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidDependencyInjectionParameterException.cs new file mode 100644 index 0000000..f80d816 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidDependencyInjectionParameterException.cs @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions +{ + internal class InvalidDependencyInjectionParameterException : Xeption + { + public InvalidDependencyInjectionParameterException(string message) : base(message) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceCollectionParameterException.cs b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceCollectionParameterException.cs new file mode 100644 index 0000000..e60b92b --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceCollectionParameterException.cs @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions +{ + internal class InvalidServiceCollectionParameterException : Xeption + { + public InvalidServiceCollectionParameterException(string message) : base(message) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceProviderParameterException.cs b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceProviderParameterException.cs new file mode 100644 index 0000000..1696126 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/DependenciesInjections/Exceptions/InvalidServiceProviderParameterException.cs @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions +{ + internal class InvalidServiceProviderParameterException : Xeption + { + public InvalidServiceProviderParameterException(string message) : base(message) + { } + } +} diff --git a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Exceptions.cs b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Exceptions.cs index 20f04a7..0f4f728 100644 --- a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Exceptions.cs +++ b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Exceptions.cs @@ -12,6 +12,7 @@ namespace STX.SPAL.Core.Services.Foundations.DependenciesInjections internal partial class DependencyInjectionService { private delegate DependencyInjection ReturningDependencyInjectionFunction(); + private delegate T ReturningGetServiceDependencyInjectionFunction(); private static DependencyInjection TryCatch( ReturningDependencyInjectionFunction returningDependencyInjectionFunction) @@ -21,12 +22,30 @@ private static DependencyInjection TryCatch( return returningDependencyInjectionFunction(); } + catch (InvalidDependencyInjectionParameterException invalidDependencyInjectionParameterException) + { + throw CreateDependencyInjectionValidationException( + invalidDependencyInjectionParameterException); + } + catch (InvalidServiceDescriptorParameterException invalidServiceDescriptorParameterException) { throw CreateDependencyInjectionValidationException( invalidServiceDescriptorParameterException); } + catch (InvalidServiceCollectionParameterException invalidServiceCollectionParameterException) + { + throw CreateDependencyInjectionValidationException( + invalidServiceCollectionParameterException); + } + + catch (InvalidServiceProviderParameterException invalidServiceProviderParameterException) + { + throw CreateDependencyInjectionValidationException( + invalidServiceProviderParameterException); + } + catch (ArgumentException argumentException) { var addServiceDescriptorException = @@ -50,11 +69,32 @@ private static DependencyInjection TryCatch( } } + private static T TryCatchGetService( + ReturningGetServiceDependencyInjectionFunction returningGetServiceDependencyInjectionFunction) + { + try + { + return returningGetServiceDependencyInjectionFunction(); + } + + catch (InvalidDependencyInjectionParameterException invalidDependencyInjectionParameterException) + { + throw CreateDependencyInjectionValidationException( + invalidDependencyInjectionParameterException); + } + + catch (InvalidServiceProviderParameterException invalidServiceProviderParameterException) + { + throw CreateDependencyInjectionValidationException( + invalidServiceProviderParameterException); + } + } + private static DependencyInjectionValidationException CreateDependencyInjectionValidationException( Xeption exception) { return new DependencyInjectionValidationException( - message: "Service Collection validation error occurred, fix errors and try again.", + message: "Dependency Injection validation error occurred, fix errors and try again.", innerException: exception); } @@ -62,7 +102,7 @@ private static DependencyInjectionValidationDependencyException CreateDependencyInjectionValidationDependencyException(Xeption exception) { return new DependencyInjectionValidationDependencyException( - message: "Service collection validation dependency error occurred, contact support.", + message: "Dependency Injection validation dependency error occurred, contact support.", innerException: exception); } @@ -70,7 +110,7 @@ private static DependencyInjectionServiceException CreateDependencyInjectionServ Xeption exception) { return new DependencyInjectionServiceException( - message: "ServiceCollection service error occurred, contact support.", + message: "Dependency Injection service error occurred, contact support.", innerException: exception); } } diff --git a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Validations.cs b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Validations.cs index ed699e4..bf35aca 100644 --- a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Validations.cs +++ b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.Validations.cs @@ -3,12 +3,19 @@ // ---------------------------------------------------------------------------------- using System; +using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections; using STX.SPAL.Core.Models.Services.Foundations.DependenciesInjections.Exceptions; namespace STX.SPAL.Core.Services.Foundations.DependenciesInjections { internal partial class DependencyInjectionService { + private static dynamic IsInvalidObject(T @object) => new + { + Condition = @object is null, + Message = "object is required" + }; + private static dynamic IsInvalidType(Type type) => new { Condition = type is null, @@ -21,7 +28,26 @@ internal partial class DependencyInjectionService Message = "Value is required" }; - private static void Validate(params (dynamic Rule, string Parameter)[] validations) + private static void ValidateDependencyInjection(params (dynamic Rule, string Parameter)[] validations) + { + var invalidDependencyInjectionParameterException = + new InvalidDependencyInjectionParameterException ( + message: "Invalid dependency injection parameter error occurred, fix errors and try again."); + + foreach ((dynamic rule, string parameter) in validations) + { + if (rule.Condition) + { + invalidDependencyInjectionParameterException.UpsertDataList( + key: parameter, + value: rule.Message); + } + } + + invalidDependencyInjectionParameterException.ThrowIfContainsErrors(); + } + + private static void ValidateServiceDescriptor(params (dynamic Rule, string Parameter)[] validations) { var invalidServiceDescriptorParameterException = new InvalidServiceDescriptorParameterException( @@ -40,9 +66,53 @@ private static void Validate(params (dynamic Rule, string Parameter)[] validatio invalidServiceDescriptorParameterException.ThrowIfContainsErrors(); } + private static void ValidateServiceCollection(params (dynamic Rule, string Parameter)[] validations) + { + var invalidServiceCollectionParameterException = + new InvalidServiceCollectionParameterException( + message: "Invalid service collection parameter error occurred, fix errors and try again."); + + foreach ((dynamic rule, string parameter) in validations) + { + if (rule.Condition) + { + invalidServiceCollectionParameterException.UpsertDataList( + key: parameter, + value: rule.Message); + } + } + + invalidServiceCollectionParameterException.ThrowIfContainsErrors(); + } + + private static void ValidateServiceProvider(params (dynamic Rule, string Parameter)[] validations) + { + var invalidServiceProviderParameterException = + new InvalidServiceProviderParameterException( + message: "Invalid service provider parameter error occurred, fix errors and try again."); + + foreach ((dynamic rule, string parameter) in validations) + { + if (rule.Condition) + { + invalidServiceProviderParameterException.UpsertDataList( + key: parameter, + value: rule.Message); + } + } + + invalidServiceProviderParameterException.ThrowIfContainsErrors(); + } + + private static void ValidateDependencyInjection(DependencyInjection dependencyInjection) + { + ValidateDependencyInjection( + (Rule: IsInvalidObject(dependencyInjection), Parameter: nameof(DependencyInjection))); + } + private static void ValidateServiceDescriptorTypes(Type spalInterfaceType, Type implementationType) { - Validate( + ValidateServiceDescriptor( (Rule: IsInvalidType(spalInterfaceType), Parameter: nameof(spalInterfaceType)), (Rule: IsInvalidType(implementationType), Parameter: nameof(implementationType))); } @@ -52,10 +122,60 @@ private static void ValidateServiceDescriptorTypesWithSpalId( string spalId, Type implementationType) { - Validate( + ValidateServiceDescriptor( (Rule: IsInvalidType(spalInterfaceType), Parameter: nameof(spalInterfaceType)), (Rule: IsInvalid(spalId), Parameter: nameof(spalId)), (Rule: IsInvalidType(implementationType), Parameter: nameof(implementationType))); } + + private static void ValidateServiceCollection(DependencyInjection dependencyInjection) + { + ValidateDependencyInjection( + (Rule: IsInvalidObject(dependencyInjection), Parameter: nameof(DependencyInjection))); + + ValidateServiceCollection( + (Rule: + IsInvalidObject(dependencyInjection.ServiceCollection), + Parameter: + nameof(DependencyInjection.ServiceCollection))); + } + + private static void ValidateServiceProvider( + DependencyInjection dependencyInjection) + { + ValidateDependencyInjection( + (Rule: + IsInvalidObject(dependencyInjection), + Parameter: + nameof(DependencyInjection))); + + ValidateServiceProvider( + (Rule: + IsInvalidObject(dependencyInjection.ServiceProvider), + Parameter: + nameof(DependencyInjection.ServiceProvider))); + } + + private static void ValidateServiceProviderWithSpalId( + DependencyInjection dependencyInjection, + string spalId) + { + ValidateDependencyInjection( + (Rule: + IsInvalidObject(dependencyInjection), + Parameter: + nameof(DependencyInjection))); + + ValidateServiceProvider( + (Rule: + IsInvalidObject(dependencyInjection.ServiceProvider), + Parameter: + nameof(DependencyInjection.ServiceProvider)), + + (Rule: + IsInvalid(spalId), + Parameter: + nameof(spalId))); + } } } diff --git a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.cs b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.cs index e1ce9d2..4b56807 100644 --- a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.cs +++ b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/DependencyInjectionService.cs @@ -23,6 +23,7 @@ public DependencyInjection RegisterServiceDescriptor( ServiceLifetime serviceLifetime) => TryCatch(() => { + ValidateDependencyInjection(dependencyInjection); ValidateServiceDescriptorTypes(spalInterfaceType, implementationType); ServiceDescriptor serviceDescriptor = @@ -43,6 +44,7 @@ public DependencyInjection RegisterServiceDescriptor( ServiceLifetime serviceLifetime) => TryCatch(() => { + ValidateDependencyInjection(dependencyInjection); ValidateServiceDescriptorTypesWithSpalId(spalInterfaceType, spalId, implementationType); ServiceDescriptor serviceDescriptor = @@ -54,5 +56,40 @@ public DependencyInjection RegisterServiceDescriptor( return dependencyInjection; }); + + public DependencyInjection BuildServiceProvider(DependencyInjection dependencyInjection) => + TryCatch(() => + { + ValidateServiceCollection(dependencyInjection); + + IServiceProvider serviceProvider = + dependencyInjectionBroker.BuildServiceProvider( + dependencyInjection.ServiceCollection); + + return new DependencyInjection + { + ServiceCollection = dependencyInjection.ServiceCollection, + ServiceProvider = serviceProvider + }; + }); + + public T GetService(DependencyInjection dependencyInjection) => + TryCatchGetService(() => + { + ValidateServiceProvider(dependencyInjection); + + return dependencyInjectionBroker.GetService( + dependencyInjection.ServiceProvider); + }); + + public T GetService(DependencyInjection dependencyInjection, string spalId) => + TryCatchGetService(() => + { + ValidateServiceProviderWithSpalId(dependencyInjection, spalId); + + return dependencyInjectionBroker.GetService( + dependencyInjection.ServiceProvider, + spalId); + }); } } diff --git a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/IDependencyInjectionService.cs b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/IDependencyInjectionService.cs index baa66ef..2d1b24a 100644 --- a/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/IDependencyInjectionService.cs +++ b/STX.SPAL.Core/Services/Foundations/DepedenciesInjections/IDependencyInjectionService.cs @@ -22,5 +22,15 @@ DependencyInjection RegisterServiceDescriptor( string spalId, Type implementationType, ServiceLifetime serviceLifetime); + + DependencyInjection BuildServiceProvider( + DependencyInjection dependencyInjection); + + T GetService( + DependencyInjection dependencyInjection); + + T GetService( + DependencyInjection dependencyInjection, + string spalId); } }