diff --git a/src/Pure.DI.Core/Core/ExceptionHandler.cs b/src/Pure.DI.Core/Core/ExceptionHandler.cs new file mode 100644 index 000000000..49b37b961 --- /dev/null +++ b/src/Pure.DI.Core/Core/ExceptionHandler.cs @@ -0,0 +1,79 @@ +namespace Pure.DI.Core; + +internal class ExceptionHandler(ILogger logger) + : IExceptionHandler +{ + public void SafeRun(T state, Action action) + { + try + { + action(state); + } + catch (AggregateException aggregateException) + { + OnAggregateException(aggregateException); + } + catch (CompileErrorException compileException) + { + OnCompileException(compileException); + } + catch (HandledException handledException) + { + OnHandledException(handledException); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception exception) + { + OnException(exception); + } + } + + private void OnAggregateException(AggregateException aggregateException) + { + foreach (var exception in aggregateException.InnerExceptions) + { + switch (exception) + { + case CompileErrorException compileError: + OnCompileException(compileError); + break; + + case HandledException handledException: + OnHandledException(handledException); + break; + + default: + OnException(exception); + break; + } + } + } + + private void OnCompileException(CompileErrorException exception) => + logger.CompileError(exception.ErrorMessage, exception.Location, exception.Id); + + private void OnHandledException(HandledException handledException) => + logger.Log( + new LogEntry( +#if DEBUG + DiagnosticSeverity.Info, +#else + DiagnosticSeverity.Hidden, +#endif + "Code generation aborted.", + default, + LogId.InfoGenerationInterrupted, + handledException)); + + private void OnException(Exception exception) => + logger.Log( + new LogEntry( + DiagnosticSeverity.Error, + "An unhandled error has occurred.", + default, + LogId.ErrorUnhandled, + exception)); +} \ No newline at end of file diff --git a/src/Pure.DI.Core/Core/Generator.cs b/src/Pure.DI.Core/Core/Generator.cs index b899b2865..fcd407dbc 100644 --- a/src/Pure.DI.Core/Core/Generator.cs +++ b/src/Pure.DI.Core/Core/Generator.cs @@ -4,7 +4,7 @@ namespace Pure.DI.Core; internal sealed class Generator( IGlobalOptions globalOptions, IProfiler profiler, - ILogger logger, + IExceptionHandler exceptionHandler, IObserversRegistry observersRegistry, IObserver logObserver, IBuilder, IEnumerable> metadataBuilder, @@ -21,67 +21,24 @@ public Unit Build(IEnumerable updates) using var logObserverToken= observersRegistry.Register(logObserver); try { - foreach (var setup in metadataBuilder.Build(updates)) - { - try - { - codeBuilderFactory().Build(setup); - } - catch (CompileErrorException compileException) - { - OnCompileException(compileException); - } - catch (HandledException handledException) - { - OnHandledException(handledException); - } - } - } - catch (OperationCanceledException) - { - } - catch (CompileErrorException compileException) - { - OnCompileException(compileException); - } - catch (HandledException handledException) - { - OnHandledException(handledException); - } - catch (Exception exception) - { - OnException(exception); + exceptionHandler.SafeRun(updates, ProcessUpdates); } finally { logObserver.OnCompleted(); } - + return Unit.Shared; } - - private void OnCompileException(CompileErrorException exception) => - logger.CompileError(exception.ErrorMessage, exception.Location, exception.Id); - - private void OnHandledException(Exception handledException) => - logger.Log( - new LogEntry( -#if DEBUG - DiagnosticSeverity.Info, -#else - DiagnosticSeverity.Hidden, -#endif - "Code generation aborted.", - default, - LogId.InfoGenerationInterrupted, - handledException)); - - private void OnException(Exception exception) => - logger.Log( - new LogEntry( - DiagnosticSeverity.Error, - "An unhandled error has occurred.", - default, - LogId.ErrorUnhandled, - exception)); + + private void ProcessUpdates(IEnumerable updates) + { + foreach (var setup in metadataBuilder.Build(updates)) + { + exceptionHandler.SafeRun(setup, BuildCode); + } + } + + private void BuildCode(MdSetup setup) => + codeBuilderFactory().Build(setup); } \ No newline at end of file diff --git a/src/Pure.DI.Core/Core/IExceptionHandler.cs b/src/Pure.DI.Core/Core/IExceptionHandler.cs new file mode 100644 index 000000000..218d63267 --- /dev/null +++ b/src/Pure.DI.Core/Core/IExceptionHandler.cs @@ -0,0 +1,6 @@ +namespace Pure.DI.Core; + +internal interface IExceptionHandler +{ + void SafeRun(T state, Action action); +} \ No newline at end of file diff --git a/src/Pure.DI.Core/Core/MetadataSyntaxWalker.cs b/src/Pure.DI.Core/Core/MetadataSyntaxWalker.cs index b13cf512f..ed474b3ec 100644 --- a/src/Pure.DI.Core/Core/MetadataSyntaxWalker.cs +++ b/src/Pure.DI.Core/Core/MetadataSyntaxWalker.cs @@ -46,8 +46,8 @@ public void Visit(IMetadataVisitor metadataVisitor, in SyntaxUpdate update) visitors.Reverse(); #if DEBUG visitors.ForEach(i => ProcessInvocation(i)); -#else - Parallel.ForEach(visitors, i => ProcessInvocation(i)); +#else + Parallel.ForEach(visitors, new ParallelOptions() { CancellationToken = cancellationToken }, i => ProcessInvocation(i)); #endif foreach (var visitor in visitors) { diff --git a/src/Pure.DI.Core/Generator.Composition.cs b/src/Pure.DI.Core/Generator.Composition.cs index 00eabbd0a..46ed7ea8d 100644 --- a/src/Pure.DI.Core/Generator.Composition.cs +++ b/src/Pure.DI.Core/Generator.Composition.cs @@ -60,6 +60,7 @@ private void Setup() => DI.Setup(nameof(Generator)) .Bind().To() .Bind().To() .Bind>().To() + .Bind().To() // Validators .Bind(Tag.Type).To()