diff --git a/CR.Exceptions.AspNet.Tests/Component/LogLevelMapTests.cs b/CR.Exceptions.AspNet.Tests/Component/LogLevelMapTests.cs index 80d9d0e..9a4c889 100644 --- a/CR.Exceptions.AspNet.Tests/Component/LogLevelMapTests.cs +++ b/CR.Exceptions.AspNet.Tests/Component/LogLevelMapTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; using Microsoft.Extensions.Logging; namespace CR.Exceptions.AspNet.Tests.Component; diff --git a/CR.Exceptions.AspNet.Tests/Component/StatusCodeMapTests.cs b/CR.Exceptions.AspNet.Tests/Component/StatusCodeMapTests.cs index f2b0e92..eeba7b8 100644 --- a/CR.Exceptions.AspNet.Tests/Component/StatusCodeMapTests.cs +++ b/CR.Exceptions.AspNet.Tests/Component/StatusCodeMapTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; using Microsoft.AspNetCore.Http; namespace CR.Exceptions.AspNet.Tests.Component; diff --git a/CR.Exceptions.AspNet.Tests/Unit/LogLevelMapBuilderTests.cs b/CR.Exceptions.AspNet.Tests/Unit/LogLevelMapBuilderTests.cs index 54e5334..63a2bca 100644 --- a/CR.Exceptions.AspNet.Tests/Unit/LogLevelMapBuilderTests.cs +++ b/CR.Exceptions.AspNet.Tests/Unit/LogLevelMapBuilderTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; namespace CR.Exceptions.AspNet.Tests.Unit; diff --git a/CR.Exceptions.AspNet.Tests/Unit/StatusCodeMapBuilderTests.cs b/CR.Exceptions.AspNet.Tests/Unit/StatusCodeMapBuilderTests.cs index 1ad0d71..2c3e3f9 100644 --- a/CR.Exceptions.AspNet.Tests/Unit/StatusCodeMapBuilderTests.cs +++ b/CR.Exceptions.AspNet.Tests/Unit/StatusCodeMapBuilderTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; namespace CR.Exceptions.AspNet.Tests.Unit; diff --git a/CR.Exceptions.AspNet/CrExceptionHandler.cs b/CR.Exceptions.AspNet/CrExceptionHandler.cs index ca3d52e..058aa8b 100644 --- a/CR.Exceptions.AspNet/CrExceptionHandler.cs +++ b/CR.Exceptions.AspNet/CrExceptionHandler.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; diff --git a/CR.Exceptions.AspNet/Mapping/LogLevelMap.cs b/CR.Exceptions.AspNet/Mapping/LogLevelMap.cs index 1ef880e..44b7057 100644 --- a/CR.Exceptions.AspNet/Mapping/LogLevelMap.cs +++ b/CR.Exceptions.AspNet/Mapping/LogLevelMap.cs @@ -1,9 +1,8 @@ -using CR.Exceptions.Mapping; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public class LogLevelMap : TypeMap { diff --git a/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilder.cs b/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilder.cs index 5660cb5..e158ca4 100644 --- a/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilder.cs +++ b/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilder.cs @@ -1,7 +1,6 @@ -using CR.Exceptions.Mapping; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public class LogLevelMapBuilder : MapBuilder { diff --git a/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilderExtensions.cs b/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilderExtensions.cs index 77a22ae..2253630 100644 --- a/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilderExtensions.cs +++ b/CR.Exceptions.AspNet/Mapping/LogLevelMapBuilderExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.Logging; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public static class LogLevelMapBuilderExtensions { diff --git a/CR.Exceptions.AspNet/Mapping/StatusCodeMap.cs b/CR.Exceptions.AspNet/Mapping/StatusCodeMap.cs index 50c85bc..f65f4e3 100644 --- a/CR.Exceptions.AspNet/Mapping/StatusCodeMap.cs +++ b/CR.Exceptions.AspNet/Mapping/StatusCodeMap.cs @@ -1,8 +1,7 @@ -using CR.Exceptions.Mapping; -using System.Collections.Frozen; +using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public class StatusCodeMap : TypeMap { diff --git a/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilder.cs b/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilder.cs index 8db409e..7df2ff7 100644 --- a/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilder.cs +++ b/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilder.cs @@ -1,7 +1,6 @@ -using CR.Exceptions.Mapping; -using System.Net; +using System.Net; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public class StatusCodeMapBuilder : MapBuilder { diff --git a/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilderExtensions.cs b/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilderExtensions.cs index 597a311..9ec57a6 100644 --- a/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilderExtensions.cs +++ b/CR.Exceptions.AspNet/Mapping/StatusCodeMapBuilderExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; -namespace CR.Exceptions.AspNet.Mapping; +namespace CR.Exceptions.AspNet; public static class StatusCodeMapBuilderExtensions { diff --git a/CR.Exceptions.AspNet/ServiceCollectionExtensions.cs b/CR.Exceptions.AspNet/ServiceCollectionExtensions.cs index c5a2965..b0cdf9d 100644 --- a/CR.Exceptions.AspNet/ServiceCollectionExtensions.cs +++ b/CR.Exceptions.AspNet/ServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.AspNet.Mapping; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace CR.Exceptions.AspNet; diff --git a/CR.Exceptions.Tests.Shared/TestUnknownException.cs b/CR.Exceptions.Tests.Shared/TestUnknownException.cs index e7d5a29..53b36ab 100644 --- a/CR.Exceptions.Tests.Shared/TestUnknownException.cs +++ b/CR.Exceptions.Tests.Shared/TestUnknownException.cs @@ -6,5 +6,5 @@ public sealed class TestUnknownException : CrException { private static readonly ImmutableArray _errors = [new("TestUnknownCode", "TestUnknownMessage")]; - public TestUnknownException() : base(_errors, "Test unknown exception message") { } + public TestUnknownException(Exception? innerException = null) : base(_errors, "Test unknown exception message", innerException) { } } \ No newline at end of file diff --git a/CR.Exceptions.Tests/Component/ExceptionFactoryTests.cs b/CR.Exceptions.Tests/Component/ExceptionFactoryTests.cs index 0790f52..5c6c811 100644 --- a/CR.Exceptions.Tests/Component/ExceptionFactoryTests.cs +++ b/CR.Exceptions.Tests/Component/ExceptionFactoryTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; namespace CR.Exceptions.Tests.Component; diff --git a/CR.Exceptions.Tests/Component/ExceptionTranslatorTests.cs b/CR.Exceptions.Tests/Component/ExceptionTranslatorTests.cs index b2a3ffc..b5a35a2 100644 --- a/CR.Exceptions.Tests/Component/ExceptionTranslatorTests.cs +++ b/CR.Exceptions.Tests/Component/ExceptionTranslatorTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; namespace CR.Exceptions.Tests.Component; @@ -50,7 +49,7 @@ public void Translate_ShouldThrow_WhenExceptionDoesNotExist() private static ExceptionTranslator GetDefaultTranslator() { return new ExceptionTranslatorBuilder() - .Map(() => new TestUnknownException()) + .Map(ex => new TestUnknownException(ex)) .Build(); } } \ No newline at end of file diff --git a/CR.Exceptions.Tests/Unit/ExceptionFactoryBuilderTests.cs b/CR.Exceptions.Tests/Unit/ExceptionFactoryBuilderTests.cs index fe13be2..741f98e 100644 --- a/CR.Exceptions.Tests/Unit/ExceptionFactoryBuilderTests.cs +++ b/CR.Exceptions.Tests/Unit/ExceptionFactoryBuilderTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; namespace CR.Exceptions.Tests.Unit; diff --git a/CR.Exceptions.Tests/Unit/ExceptionTranslatorBuilderTests.cs b/CR.Exceptions.Tests/Unit/ExceptionTranslatorBuilderTests.cs index 0bfa369..18531fd 100644 --- a/CR.Exceptions.Tests/Unit/ExceptionTranslatorBuilderTests.cs +++ b/CR.Exceptions.Tests/Unit/ExceptionTranslatorBuilderTests.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.Mapping; -using CR.Exceptions.Tests.Shared; +using CR.Exceptions.Tests.Shared; namespace CR.Exceptions.Tests.Unit; @@ -9,8 +8,8 @@ public sealed class ExceptionTranslatorBuilderTests public void Map_ShouldThrow_WhenDuplicateRegistered() { var builder = new ExceptionTranslatorBuilder() - .Map(() => new TestUnknownException()); + .Map(ex => new TestUnknownException(ex)); - Assert.ThrowsAny(() => builder.Map(() => new TestUnknownException())); + Assert.ThrowsAny(() => builder.Map(ex => new TestUnknownException(ex))); } } \ No newline at end of file diff --git a/CR.Exceptions/CrException.cs b/CR.Exceptions/CrException.cs index 83ba31c..1f12fc6 100644 --- a/CR.Exceptions/CrException.cs +++ b/CR.Exceptions/CrException.cs @@ -1,5 +1,4 @@ -using CR.Exceptions.Extensions; -using System.Collections.Immutable; +using System.Collections.Immutable; namespace CR.Exceptions; diff --git a/CR.Exceptions/Extensions/FuncExtensions.cs b/CR.Exceptions/Extensions/FuncExtensions.cs deleted file mode 100644 index 12c1be1..0000000 --- a/CR.Exceptions/Extensions/FuncExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace CR.Exceptions.Extensions; - -internal static class FuncExtensions -{ - extension(Func func) - { - public TResult ToResult([CallerArgumentExpression(nameof(func))] string? paramName = null) - { - ArgumentNullException.ThrowIfNull(func, paramName); - return func() ?? throw new NullReferenceException("delegate return null"); - } - } -} \ No newline at end of file diff --git a/CR.Exceptions/Extensions/ImmutableArrayExtensions.cs b/CR.Exceptions/Extensions/ImmutableArrayExtensions.cs index 5b1a635..1de079b 100644 --- a/CR.Exceptions/Extensions/ImmutableArrayExtensions.cs +++ b/CR.Exceptions/Extensions/ImmutableArrayExtensions.cs @@ -1,7 +1,7 @@ using System.Collections.Immutable; using System.Runtime.CompilerServices; -namespace CR.Exceptions.Extensions; +namespace CR.Exceptions; internal static class ImmutableArrayExtensions { diff --git a/CR.Exceptions/Mapping/ExceptionFactory.cs b/CR.Exceptions/Mapping/ExceptionFactory.cs index 579016c..e1b7913 100644 --- a/CR.Exceptions/Mapping/ExceptionFactory.cs +++ b/CR.Exceptions/Mapping/ExceptionFactory.cs @@ -1,16 +1,20 @@ -using CR.Exceptions.Extensions; -using System.Collections.Frozen; +using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; public class ExceptionFactory : Map> { internal ExceptionFactory(FrozenDictionary> dictionary) : base(dictionary) { } public CrException Create(string code) - => GetValue(code).ToResult(); + => ExecuteFactory(GetValue(code)); public bool TryCreate(string code, [MaybeNullWhen(false)] out CrException exception) - => (exception = TryGetValue(code, out var factory) ? factory.ToResult() : null) != null; + => (exception = TryGetValue(code, out var factory) ? ExecuteFactory(factory) : null) != null; + + private static CrException ExecuteFactory(Func factory) + { + return factory() ?? throw new InvalidOperationException($"{nameof(factory)} '{factory.Method.Name}' returned null."); + } } \ No newline at end of file diff --git a/CR.Exceptions/Mapping/ExceptionFactoryBuilder.cs b/CR.Exceptions/Mapping/ExceptionFactoryBuilder.cs index a85e9e2..58d2b9a 100644 --- a/CR.Exceptions/Mapping/ExceptionFactoryBuilder.cs +++ b/CR.Exceptions/Mapping/ExceptionFactoryBuilder.cs @@ -1,4 +1,4 @@ -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; public class ExceptionFactoryBuilder : MapBuilder> { diff --git a/CR.Exceptions/Mapping/ExceptionTranslator.cs b/CR.Exceptions/Mapping/ExceptionTranslator.cs index 62d399d..23ebb75 100644 --- a/CR.Exceptions/Mapping/ExceptionTranslator.cs +++ b/CR.Exceptions/Mapping/ExceptionTranslator.cs @@ -1,16 +1,22 @@ -using CR.Exceptions.Extensions; -using System.Collections.Frozen; +using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; -public class ExceptionTranslator : TypeMap> +public class ExceptionTranslator : TypeMap> { - internal ExceptionTranslator(FrozenDictionary> dictionary) : base(dictionary) { } + internal ExceptionTranslator(FrozenDictionary> dictionary) : base(dictionary) { } - public CrException Translate(CrException exception) - => GetByHierarchy(exception.GetType()).ToResult(); + public CrException Translate(Exception exception) + => ExecuteTranslator(exception, GetByHierarchy(exception.GetType())); - public bool TryTranslate(CrException exception, [MaybeNullWhen(false)] out CrException translated) - => (translated = TryGetByHierarchy(exception.GetType(), out var translator) ? translator.ToResult() : null) != null; + public bool TryTranslate(Exception exception, [MaybeNullWhen(false)] out CrException translated) + => (translated = TryGetByHierarchy(exception.GetType(), out var translator) ? ExecuteTranslator(exception, translator) : null) != null; + + private static CrException ExecuteTranslator(Exception innerException, Func translator) + { + return + translator(innerException) ?? + throw new InvalidOperationException($"{nameof(translator)} '{translator.Method.Name}' returned null."); + } } \ No newline at end of file diff --git a/CR.Exceptions/Mapping/ExceptionTranslatorBuilder.cs b/CR.Exceptions/Mapping/ExceptionTranslatorBuilder.cs index 8e227f3..bcba23d 100644 --- a/CR.Exceptions/Mapping/ExceptionTranslatorBuilder.cs +++ b/CR.Exceptions/Mapping/ExceptionTranslatorBuilder.cs @@ -1,8 +1,8 @@ -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; -public class ExceptionTranslatorBuilder : MapBuilder> +public class ExceptionTranslatorBuilder : MapBuilder> { - public ExceptionTranslatorBuilder Map(Func translator) where TException : CrException + public ExceptionTranslatorBuilder Map(Func translator) where TException : Exception { AddPair(typeof(TException), translator); return this; diff --git a/CR.Exceptions/Mapping/Map.cs b/CR.Exceptions/Mapping/Map.cs index 769c35a..e90b67a 100644 --- a/CR.Exceptions/Mapping/Map.cs +++ b/CR.Exceptions/Mapping/Map.cs @@ -1,7 +1,7 @@ using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; public abstract class Map where TKey : notnull { @@ -20,6 +20,6 @@ protected TValue GetValue(TKey key) protected bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) => _dictionary.TryGetValue(key, out value); - protected KeyNotFoundException CreateKeyNotFoundException(TKey key) + protected KeyNotFoundException CreateKeyNotFoundException(TKey? key) => new($"Key '{key?.ToString() ?? "null"}' in map is not found."); } \ No newline at end of file diff --git a/CR.Exceptions/Mapping/MapBuilder.cs b/CR.Exceptions/Mapping/MapBuilder.cs index b1f9558..73d0819 100644 --- a/CR.Exceptions/Mapping/MapBuilder.cs +++ b/CR.Exceptions/Mapping/MapBuilder.cs @@ -1,6 +1,6 @@ using System.Collections.Frozen; -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; public abstract class MapBuilder where TKey : notnull { diff --git a/CR.Exceptions/Mapping/TypeMap.cs b/CR.Exceptions/Mapping/TypeMap.cs index b671b46..7d5dc2d 100644 --- a/CR.Exceptions/Mapping/TypeMap.cs +++ b/CR.Exceptions/Mapping/TypeMap.cs @@ -1,7 +1,7 @@ using System.Collections.Frozen; using System.Diagnostics.CodeAnalysis; -namespace CR.Exceptions.Mapping; +namespace CR.Exceptions; public abstract class TypeMap : Map { diff --git a/CR.Exceptions/README.md b/CR.Exceptions/README.md index 815bfa0..7c12da4 100644 --- a/CR.Exceptions/README.md +++ b/CR.Exceptions/README.md @@ -61,13 +61,8 @@ Example: ```csharp public sealed class UserNotFoundException : NotFoundException { - public UserNotFoundException() - : base( - [ - new CrError( - "IdentityUserNotFound", - "User was not found.") - ]) + public UserNotFoundException() + : base([new CrError("IdentityUserNotFound","User was not found.")]) { } } @@ -124,14 +119,14 @@ Registration: ```csharp ExceptionTranslator translator = new ExceptionTranslatorBuilder() .Map( - static () => new UserNotFoundException()) + static innerException => new UserNotFoundException(innerException)) .Build(); ``` Usage: ```csharp -catch (KeycloakUserNotFoundException ex) +catch (Exception ex) { throw translator.Translate(ex); } diff --git a/Directory.Build.props b/Directory.Build.props index c795950..be79613 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,4 +1,5 @@ + apptade apptade @@ -12,4 +13,11 @@ Apache-2.0 CrCore + + + latest + Recommended + true + + \ No newline at end of file