diff --git a/STX.SPAL.Core.Tests.Unit/STX.SPAL.Core.Tests.Unit.csproj b/STX.SPAL.Core.Tests.Unit/STX.SPAL.Core.Tests.Unit.csproj index 9897380..9823055 100644 --- a/STX.SPAL.Core.Tests.Unit/STX.SPAL.Core.Tests.Unit.csproj +++ b/STX.SPAL.Core.Tests.Unit/STX.SPAL.Core.Tests.Unit.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -9,7 +9,10 @@ - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive @@ -25,4 +28,8 @@ + + + + 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 new file mode 100644 index 0000000..95e8edc --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Exceptions.GetAssembly.cs @@ -0,0 +1,150 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Reflection; +using FluentAssertions; +using Moq; +using STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.Assemblies +{ + public partial class AssemblyServiceTests + { + [Theory] + [MemberData(nameof(AssemblyLoadDependencyExceptions))] + private void ShouldThrowDependencyExceptionOnLoadAssemblyIfExternalExceptionOccurs( + Exception externalException) + { + // given + string someAssemblyPath = CreateRandomPathAssembly(); + + var assemblyLoadException = + new AssemblyLoadException( + message: "Assembly load error occurred, contact support.", + innerException: externalException); + + var expectedAssemblyDependencyException = + new AssemblyDependencyException( + message: "Assembly dependency error occurred, contact support.", + innerException: assemblyLoadException); + + this.assemblyBroker + .Setup(broker => + broker.GetAssembly( + It.Is(actualAssemblyPath => + actualAssemblyPath == someAssemblyPath))) + .Throws(externalException); + + // when + Func getAssemblyFunction = () => + this.assemblyService.GetAssembly(someAssemblyPath); + + AssemblyDependencyException actualAssemblyDependencyException = + Assert.Throws( + getAssemblyFunction); + + //then + actualAssemblyDependencyException.Should().BeEquivalentTo( + expectedAssemblyDependencyException); + + this.assemblyBroker + .Verify(broker => + broker.GetAssembly(It.IsAny()), + Times.Once); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + + [Theory] + [MemberData(nameof(AssemblyLoadValidationDependencyExceptions))] + private void ShouldThrowValidationDependencyExceptionOnLoadAssemblyIfExternalExceptionOccurs( + Exception externalException) + { + // given + string someAssemblyPath = CreateRandomPathAssembly(); + + var assemblyLoadException = + new AssemblyLoadException( + message: "Assembly load error occurred, contact support.", + innerException: externalException); + + var expectedAssemblyValidationDependencyException = + new AssemblyValidationDependencyException( + message: "Assembly validation dependency error occurred, contact support.", + innerException: assemblyLoadException); + + this.assemblyBroker + .Setup(broker => + broker.GetAssembly( + It.Is(actualAssemblyPath => + actualAssemblyPath == someAssemblyPath))) + .Throws(externalException); + + // when + Func getAssemblyFunction = () => + this.assemblyService.GetAssembly(someAssemblyPath); + + AssemblyValidationDependencyException actualAssemblyValidationDependencyException = + Assert.Throws( + getAssemblyFunction); + + //then + actualAssemblyValidationDependencyException.Should().BeEquivalentTo( + expectedAssemblyValidationDependencyException); + + this.assemblyBroker + .Verify(broker => + broker.GetAssembly(It.IsAny()), + Times.Once); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + + [Theory] + [MemberData(nameof(AssemblyLoadServiceExceptions))] + private void ShouldThrowServiceExceptionOnLoadAssemblyIfExceptionOccurs( + Exception externalException) + { + // given + string someAssemblyPath = CreateRandomPathAssembly(); + + var assemblyLoadException = + new FailedAssemblyServiceException( + message: "Failed service error occurred, contact support.", + innerException: externalException); + + var expectedAssemblyServiceException = + new AssemblyServiceException( + message: "Assembly service error occurred, contact support.", + innerException: assemblyLoadException); + + this.assemblyBroker + .Setup(broker => + broker.GetAssembly( + It.Is(actualAssemblyPath => + actualAssemblyPath == someAssemblyPath))) + .Throws(externalException); + + // when + Func getAssemblyFunction = () => + this.assemblyService.GetAssembly(someAssemblyPath); + + AssemblyServiceException actualAssemblyServiceException = + Assert.Throws( + getAssemblyFunction); + + //then + actualAssemblyServiceException.Should().BeEquivalentTo( + expectedAssemblyServiceException); + + this.assemblyBroker + .Verify(broker => + broker.GetAssembly(It.IsAny()), + Times.Once); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + } +} 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 new file mode 100644 index 0000000..4ed031b --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetApplicationPathsAssemblies.cs @@ -0,0 +1,46 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Threading.Tasks; +using FluentAssertions; +using Moq; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.Assemblies +{ + public partial class AssemblyServiceTests + { + [Fact] + private void ShouldGetApplicationPathAssemblies() + { + // given + string[] randomApplicationPathsAssemblies = + CreateRandomPathArray(); + + string[] expectedApplicationPathsAssemblies = + randomApplicationPathsAssemblies; + + string[] returnedApplicationPathsAssemblies = + randomApplicationPathsAssemblies; + + this.assemblyBroker + .Setup(broker => broker.GetApplicationPathsAssemblies()) + .Returns(returnedApplicationPathsAssemblies); + + // when + string[] actualApplicationPathsAssemblies = + this.assemblyService.GetApplicationPathsAssemblies(); + + //then + actualApplicationPathsAssemblies.Should() + .BeEquivalentTo(expectedApplicationPathsAssemblies); + + this.assemblyBroker.Verify( + broker => + broker.GetApplicationPathsAssemblies(), + Times.Once); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + } +} 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 new file mode 100644 index 0000000..f564a14 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Logic.GetAssembly.cs @@ -0,0 +1,48 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Reflection; +using System.Threading.Tasks; +using FluentAssertions; +using Moq; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.Assemblies +{ + public partial class AssemblyServiceTests + { + [Fact] + private void ShouldGetAssembly() + { + // given + Assembly randomAssembly = CreateRandomAssembly(); + Assembly expectedAssembly = randomAssembly; + Assembly returnedAssembly = randomAssembly; + string randomPathAssembly = CreateRandomPathAssembly(); + string inputPathAssembly = randomPathAssembly; + + this.assemblyBroker + .Setup(broker => + broker.GetAssembly( + It.Is(actualPathAssembly => + actualPathAssembly == inputPathAssembly))) + .Returns(returnedAssembly); + + // when + Assembly actualAssembly = + this.assemblyService.GetAssembly(inputPathAssembly); + + //then + actualAssembly.Should().BeSameAs(expectedAssembly); + + this.assemblyBroker.Verify( + broker => + broker.GetAssembly( + It.Is(actualPathAssembly => + actualPathAssembly == inputPathAssembly)), + Times.Once); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + } +} 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 new file mode 100644 index 0000000..d410865 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.Validations.GetAssembly.cs @@ -0,0 +1,71 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.Reflection; +using FluentAssertions; +using Moq; +using STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.Assemblies +{ + public partial class AssemblyServiceTests + { + [Theory] + [InlineData(null, "Value is required")] + [InlineData("", "Value is required")] + [InlineData(" ", "Value is required")] + [InlineData("file", "Value is not a valid assembly path")] + private void ShouldThrowValidationExceptionIfInvalidAssemblyPath( + string assemblyPath, + string exceptionMessage) + { + // given + Assembly randomAssembly = CreateRandomAssembly(); + Assembly expectedAssembly = randomAssembly; + Assembly returnedAssembly = randomAssembly; + string randomPathAssembly = CreateRandomPathAssembly(); + string inputAssemblyPath = assemblyPath; + + var invalidAssemblyPathException = + new InvalidAssemblyPathException( + message: "Invalid assembly path error occurred, fix errors and try again."); + + invalidAssemblyPathException.AddData( + key: nameof(assemblyPath), + values: exceptionMessage + ); + + var expectedAssemblyValidationException = + new AssemblyValidationException( + message: "Assembly validation error occurred, fix errors and try again.", + innerException: invalidAssemblyPathException); + + this.assemblyBroker + .Setup(broker => + broker.GetAssembly( + It.Is(actualAssemblyPath => + actualAssemblyPath == inputAssemblyPath))); + + // when + Func getAssemblyFunction = () => + this.assemblyService.GetAssembly(inputAssemblyPath); + + AssemblyValidationException actualAssemblyValidationException = + Assert.Throws( + getAssemblyFunction); + + //then + actualAssemblyValidationException.Should().BeEquivalentTo( + expectedAssemblyValidationException); + + this.assemblyBroker + .Verify(broker => + broker.GetAssembly(It.IsAny()), + Times.Never); + + this.assemblyBroker.VerifyNoOtherCalls(); + } + } +} diff --git a/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.cs b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.cs new file mode 100644 index 0000000..858aa30 --- /dev/null +++ b/STX.SPAL.Core.Tests.Unit/Services/Foundations/Assemblies/AssemblyServiceTests.cs @@ -0,0 +1,97 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Security; +using Moq; +using STX.SPAL.Core.Brokers.Assemblies; +using STX.SPAL.Core.Services.Foundations.Assemblies; +using Tynamix.ObjectFiller; + +namespace STX.SPAL.Core.Tests.Unit.Services.Foundations.Assemblies +{ + public partial class AssemblyServiceTests + { + private readonly Mock assemblyBroker; + private readonly IAssemblyService assemblyService; + + public AssemblyServiceTests() + { + this.assemblyBroker = new Mock(); + + this.assemblyService = + new AssemblyService(assemblyBroker.Object); + } + + private static string GetRandomString() => + new MnemonicString().GetValue(); + + private static int GetRandomNumber() => + new IntRange(min: 2, max: 10).GetValue(); + + private static string CreateRandomPathAssembly() + { + string randomPathName = GetRandomString(); + string randomFileName = GetRandomString(); + + return $"{Path.Combine(randomPathName, randomFileName)}.dll"; + } + + private static string[] CreateRandomPathArray() + { + return Enumerable.Range(0, GetRandomNumber()) + .Select(i => CreateRandomPathAssembly()) + .ToArray(); + } + + private static Assembly CreateRandomAssembly() + { + string randomAssemblyName = GetRandomString(); + var assemblyName = + new AssemblyName("randomAssemblyName"); + + AssemblyBuilder assemblyBuilder = + AssemblyBuilder.DefineDynamicAssembly( + assemblyName, + AssemblyBuilderAccess.Run); + + return assemblyBuilder; + } + + public static TheoryData AssemblyLoadDependencyExceptions() + { + return new TheoryData + { + new SecurityException(), + new FileLoadException(), + new FileNotFoundException(), + new BadImageFormatException(), + new InvalidOperationException(), + new NotSupportedException(), + new IOException(), + new UnauthorizedAccessException() + }; + } + + public static TheoryData AssemblyLoadValidationDependencyExceptions() + { + return new TheoryData + { + new ArgumentException() + }; + } + + public static TheoryData AssemblyLoadServiceExceptions() + { + return new TheoryData + { + new Exception() + }; + } + } +} diff --git a/STX.SPAL.Core/Brokers/Assemblies/IAssemblyBroker.cs b/STX.SPAL.Core/Brokers/Assemblies/IAssemblyBroker.cs index d36bfa2..6c88634 100644 --- a/STX.SPAL.Core/Brokers/Assemblies/IAssemblyBroker.cs +++ b/STX.SPAL.Core/Brokers/Assemblies/IAssemblyBroker.cs @@ -8,6 +8,7 @@ namespace STX.SPAL.Core.Brokers.Assemblies { internal partial interface IAssemblyBroker { + string[] GetApplicationPathsAssemblies(); Assembly GetAssembly(string fullPath); } } diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyDependencyException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyDependencyException.cs new file mode 100644 index 0000000..c142ad6 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyDependencyException.cs @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + internal class AssemblyDependencyException : Xeption + { + public AssemblyDependencyException(string message, Xeption innerException) + : base(message, innerException) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyLoadException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyLoadException.cs new file mode 100644 index 0000000..29800ad --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyLoadException.cs @@ -0,0 +1,16 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + internal class AssemblyLoadException : Xeption + { + public AssemblyLoadException(string message, Exception innerException) + : base(message: message, innerException) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyServiceException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyServiceException.cs new file mode 100644 index 0000000..df0d174 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyServiceException.cs @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + internal class AssemblyServiceException : Xeption + { + public AssemblyServiceException(string message, Xeption innerException) + : base(message, innerException) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationDependencyException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationDependencyException.cs new file mode 100644 index 0000000..a58ab43 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationDependencyException.cs @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + internal class AssemblyValidationDependencyException : Xeption + { + public AssemblyValidationDependencyException(string message, Xeption innerException) + : base(message, innerException) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationException.cs new file mode 100644 index 0000000..139b935 --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/AssemblyValidationException.cs @@ -0,0 +1,15 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + public class AssemblyValidationException : Xeption + { + public AssemblyValidationException(string message, Xeption innerException) + : base(message, innerException) + { } + } +} \ No newline at end of file diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/FailedAssemblyServiceException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/FailedAssemblyServiceException.cs new file mode 100644 index 0000000..557b9dc --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/FailedAssemblyServiceException.cs @@ -0,0 +1,16 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System; +using Xeptions; + +namespace STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions +{ + internal class FailedAssemblyServiceException : Xeption + { + public FailedAssemblyServiceException(string message, Exception innerException) + : base(message, innerException) + { } + } +} diff --git a/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/InvalidAssemblyPathException.cs b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/InvalidAssemblyPathException.cs new file mode 100644 index 0000000..ae311eb --- /dev/null +++ b/STX.SPAL.Core/Models/Services/Foundations/Assemblies/Exceptions/InvalidAssemblyPathException.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.Assemblies.Exceptions +{ + internal class InvalidAssemblyPathException : Xeption + { + public InvalidAssemblyPathException(string message) : base(message) + { } + } +} diff --git a/STX.SPAL.Core/STX.SPAL.Core.csproj b/STX.SPAL.Core/STX.SPAL.Core.csproj index 48b846e..849e8b3 100644 --- a/STX.SPAL.Core/STX.SPAL.Core.csproj +++ b/STX.SPAL.Core/STX.SPAL.Core.csproj @@ -1,13 +1,23 @@  - - net8.0 - disable - disable - - - - - + + net8.0 + disable + disable + + + + + + + + + + + + + + + diff --git a/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Exceptions.cs b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Exceptions.cs new file mode 100644 index 0000000..c43e5fa --- /dev/null +++ b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Exceptions.cs @@ -0,0 +1,135 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.IO; +using System; +using System.Reflection; +using System.Security; +using STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions; +using Xeptions; +using System.Runtime.InteropServices; + +namespace STX.SPAL.Core.Services.Foundations.Assemblies +{ + internal partial class AssemblyService + { + private delegate Assembly ReturningAssemblyFunction(); + + private static Assembly TryCatch(ReturningAssemblyFunction returningAssemblyFunction) + { + try + { + return returningAssemblyFunction(); + } + + catch (InvalidAssemblyPathException invalidAssemblyPathException) + { + throw CreateAssemblyValidationException( + invalidAssemblyPathException); + } + + catch (SecurityException securityException) + { + throw CreateAssemblyDependencyException( + securityException); + } + + catch (FileLoadException fileLoadException) + { + throw CreateAssemblyDependencyException( + fileLoadException); + } + + catch (FileNotFoundException fileNotFoundException) + { + throw CreateAssemblyDependencyException( + fileNotFoundException); + } + + catch (BadImageFormatException badImageFormatException) + { + throw CreateAssemblyDependencyException( + badImageFormatException); + } + + catch (InvalidOperationException invalidOperationException) + { + throw CreateAssemblyDependencyException( + invalidOperationException); + } + + catch (NotSupportedException notSupportedException) + { + throw CreateAssemblyDependencyException( + notSupportedException); + } + + catch (IOException iOException) + { + throw CreateAssemblyDependencyException(iOException); + } + + catch (UnauthorizedAccessException unauthorizedAccessException) + { + throw CreateAssemblyDependencyException( + unauthorizedAccessException); + } + + catch (ArgumentException argumentException) + { + throw CreateAssemblyValidationDependencyException( + argumentException); + } + + catch (Exception exception) + { + throw CreateAssemblyServiceException( + exception); + } + } + + private static AssemblyValidationException CreateAssemblyValidationException(Xeption exception) + { + return new AssemblyValidationException( + message: "Assembly validation error occurred, fix errors and try again.", + innerException: exception); + } + + private static AssemblyDependencyException CreateAssemblyDependencyException(Exception exception) + { + var assemblyLoadException = + new AssemblyLoadException( + message: "Assembly load error occurred, contact support.", + innerException: exception); + + return new AssemblyDependencyException( + message: "Assembly dependency error occurred, contact support.", + innerException: assemblyLoadException); + } + + private static AssemblyValidationDependencyException CreateAssemblyValidationDependencyException(Exception exception) + { + var assemblyLoadException = + new AssemblyLoadException( + message: "Assembly load error occurred, contact support.", + innerException: exception); + + return new AssemblyValidationDependencyException( + message: "Assembly validation dependency error occurred, contact support.", + innerException: assemblyLoadException); + } + + private static AssemblyServiceException CreateAssemblyServiceException(Exception exception) + { + var failedAssemblyServiceException = + new FailedAssemblyServiceException( + message: "Failed service error occurred, contact support.", + innerException: exception); + + return new AssemblyServiceException( + message: "Assembly service error occurred, contact support.", + innerException: failedAssemblyServiceException); + } + } +} diff --git a/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Validations.cs b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Validations.cs new file mode 100644 index 0000000..a5cbfa1 --- /dev/null +++ b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.Validations.cs @@ -0,0 +1,52 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using STX.SPAL.Core.Models.Services.Foundations.Assemblies.Exceptions; + +namespace STX.SPAL.Core.Services.Foundations.Assemblies +{ + internal partial class AssemblyService + { + private static dynamic IsInvalid(string text) => new + { + Condition = string.IsNullOrWhiteSpace(text), + Message = "Value is required" + }; + + private static dynamic IsInvalidAssemblyPath(string assemblyPath) => + new + { + Condition = !assemblyPath.EndsWith(".dll"), + Message = "Value is not a valid assembly path" + }; + + private static void Validate(params (dynamic Rule, string Parameter)[] validations) + { + var invalidAssemblyPathException = + new InvalidAssemblyPathException( + message: "Invalid assembly path error occurred, fix errors and try again."); + + foreach ((dynamic rule, string parameter) in validations) + { + if (rule.Condition) + { + invalidAssemblyPathException.UpsertDataList( + key: parameter, + value: rule.Message); + } + } + + invalidAssemblyPathException.ThrowIfContainsErrors(); + } + + private static void ValidateAssemblyPath(string assemblyPath) + { + Validate( + (Rule: IsInvalid(assemblyPath), Parameter: nameof(assemblyPath))); + + Validate( + (Rule: IsInvalidAssemblyPath(assemblyPath), Parameter: nameof(assemblyPath))); + } + } +} diff --git a/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.cs b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.cs new file mode 100644 index 0000000..27e9895 --- /dev/null +++ b/STX.SPAL.Core/Services/Foundations/Assemblies/AssemblyService.cs @@ -0,0 +1,30 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Reflection; +using STX.SPAL.Core.Brokers.Assemblies; + +namespace STX.SPAL.Core.Services.Foundations.Assemblies +{ + internal partial class AssemblyService : IAssemblyService + { + private readonly IAssemblyBroker assemblyBroker; + + public AssemblyService(IAssemblyBroker assemblyBroker) + { + this.assemblyBroker = assemblyBroker; + } + + public string[] GetApplicationPathsAssemblies() => + this.assemblyBroker.GetApplicationPathsAssemblies(); + + public Assembly GetAssembly(string assemblyPath) => + TryCatch(() => + { + ValidateAssemblyPath(assemblyPath); + + return this.assemblyBroker.GetAssembly(assemblyPath); + }); + } +} diff --git a/STX.SPAL.Core/Services/Foundations/Assemblies/IAssemblyService.cs b/STX.SPAL.Core/Services/Foundations/Assemblies/IAssemblyService.cs new file mode 100644 index 0000000..b68a93c --- /dev/null +++ b/STX.SPAL.Core/Services/Foundations/Assemblies/IAssemblyService.cs @@ -0,0 +1,14 @@ +// ---------------------------------------------------------------------------------- +// Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers +// ---------------------------------------------------------------------------------- + +using System.Reflection; + +namespace STX.SPAL.Core.Services.Foundations.Assemblies +{ + internal interface IAssemblyService + { + string[] GetApplicationPathsAssemblies(); + Assembly GetAssembly(string fullPath); + } +}