From 2945cee95e25b6d7171b13a98e7618f9c31461f5 Mon Sep 17 00:00:00 2001 From: Muhammad Rehan Saeed Date: Wed, 10 Mar 2021 10:25:22 +0000 Subject: [PATCH] Enable C# 8 nullable reference types --- .../BenchmarkException.cs | 4 +- .../BenchmarkExceptionDestructurer.cs | 8 +- .../DestructuringBenchmark.cs | 14 +-- .../ExceptionPropertiesBag.cs | 10 +- Directory.Build.props | 1 + .../DbUpdateExceptionDestructurer.cs | 2 +- .../Destructurers/SqlExceptionDestructurer.cs | 2 +- .../Destructurers/SqlExceptionDestructurer.cs | 4 +- .../Core/DestructuringOptionsBuilder.cs | 2 +- .../Core/ExceptionEnricher.cs | 2 +- .../Core/ExceptionPropertiesBag.cs | 10 +- .../Core/IDestructuringOptions.cs | 82 ++++++++-------- .../Core/IExceptionPropertiesBag.cs | 4 +- .../AggregateExceptionDestructurer.cs | 2 +- .../ArgumentExceptionDestructurer.cs | 2 +- ...ArgumentOutOfRangeExceptionDestructurer.cs | 2 +- .../Destructurers/ExceptionDestructurer.cs | 6 +- .../Destructurers/IExceptionDestructurer.cs | 2 +- .../OperationCanceledExceptionDestructurer.cs | 2 +- .../ReflectionBasedDestructurer.cs | 85 ++++++++-------- ...ReflectionTypeLoadExceptionDestructurer.cs | 25 ++++- .../SocketExceptionDestructurer.cs | 2 +- .../TaskCanceledExceptionDestructurer.cs | 6 +- .../DictionaryExtensions.cs | 15 ++- .../CompositeExceptionPropertyFilter.cs | 2 +- .../Filters/IExceptionPropertyFilter.cs | 2 +- .../IgnorePropertyByNameExceptionFilter.cs | 4 +- .../DbUpdateExceptionDestructurerTest.cs | 6 +- .../ExceptionDestructurerTest.cs | 4 +- .../ExceptionPropertiesBagTest.cs | 4 +- .../Destructurers/LogJsonOutputUtils.cs | 8 +- .../ReflectionBasedDestructurerTest.cs | 98 ++++++++++--------- .../CompositeExceptionPropertyFilterTest.cs | 4 +- Tools/ExceptionFinderTool/Program.cs | 55 +---------- 34 files changed, 235 insertions(+), 246 deletions(-) diff --git a/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkException.cs b/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkException.cs index 1046e9bc..8725d9f9 100644 --- a/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkException.cs +++ b/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkException.cs @@ -27,10 +27,10 @@ protected BenchmarkException( { } - public string ParamString { get; set; } + public string? ParamString { get; set; } public int ParamInt { get; set; } - public Point Point { get; set; } + public Point? Point { get; set; } } } diff --git a/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkExceptionDestructurer.cs b/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkExceptionDestructurer.cs index 2f08b36c..1a2acc61 100644 --- a/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkExceptionDestructurer.cs +++ b/Benchmarks/Serilog.Exceptions.Benchmark/BenchmarkExceptionDestructurer.cs @@ -18,7 +18,7 @@ public class BenchmarkExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); @@ -26,10 +26,10 @@ public override void Destructure( var benchmarkException = (BenchmarkException)exception; propertiesBag.AddProperty("ParamString", benchmarkException.ParamString); propertiesBag.AddProperty("ParamInt", benchmarkException.ParamInt); - propertiesBag.AddProperty("Point", new Dictionary + propertiesBag.AddProperty("Point", new Dictionary { - { "X", benchmarkException.Point.X }, - { "Y", benchmarkException.Point.Y }, + { "X", benchmarkException.Point?.X }, + { "Y", benchmarkException.Point?.Y }, }); #pragma warning restore CA1062 // Validate arguments of public methods } diff --git a/Benchmarks/Serilog.Exceptions.Benchmark/DestructuringBenchmark.cs b/Benchmarks/Serilog.Exceptions.Benchmark/DestructuringBenchmark.cs index 1b011963..06e7faa5 100644 --- a/Benchmarks/Serilog.Exceptions.Benchmark/DestructuringBenchmark.cs +++ b/Benchmarks/Serilog.Exceptions.Benchmark/DestructuringBenchmark.cs @@ -19,7 +19,7 @@ public class DestructuringBenchmark { private readonly ReflectionBasedDestructurer reflectionBasedDestructurer = new(10); private readonly BenchmarkExceptionDestructurer benchmarkExceptionDestructurer = new(); - private BenchmarkException benchmarkException; + private BenchmarkException benchmarkException = default!; [GlobalSetup] public void Setup() @@ -39,36 +39,36 @@ public void Setup() } } - public IReadOnlyDictionary DestructureUsingReflectionDestructurer(Exception ex) + public IReadOnlyDictionary DestructureUsingReflectionDestructurer(Exception ex) { var bag = new ExceptionPropertiesBag(ex); this.reflectionBasedDestructurer.Destructure( ex, bag, - null); + null!); return bag.GetResultDictionary(); } [Benchmark] - public IReadOnlyDictionary ReflectionDestructurer() => + public IReadOnlyDictionary ReflectionDestructurer() => this.DestructureUsingReflectionDestructurer(this.benchmarkException); - public IReadOnlyDictionary DestructureUsingCustomDestructurer(Exception ex) + public IReadOnlyDictionary DestructureUsingCustomDestructurer(Exception ex) { var bag = new ExceptionPropertiesBag(ex); this.benchmarkExceptionDestructurer.Destructure( ex, bag, - null); + null!); return bag.GetResultDictionary(); } [Benchmark] - public IReadOnlyDictionary CustomDestructurer() => + public IReadOnlyDictionary CustomDestructurer() => this.DestructureUsingCustomDestructurer(this.benchmarkException); } } diff --git a/Benchmarks/Serilog.Exceptions.Benchmark/ExceptionPropertiesBag.cs b/Benchmarks/Serilog.Exceptions.Benchmark/ExceptionPropertiesBag.cs index f45a47e4..279a14fc 100644 --- a/Benchmarks/Serilog.Exceptions.Benchmark/ExceptionPropertiesBag.cs +++ b/Benchmarks/Serilog.Exceptions.Benchmark/ExceptionPropertiesBag.cs @@ -8,26 +8,26 @@ namespace Serilog.Exceptions.Benchmark internal class ExceptionPropertiesBag : IExceptionPropertiesBag { private readonly Exception exception; - private readonly IExceptionPropertyFilter filter; - private readonly Dictionary properties = new(); + private readonly IExceptionPropertyFilter? filter; + private readonly Dictionary properties = new(); // We keep a note on whether the results were collected to be sure that // after that there are no changes. This is the application of fail-fast principle. private bool resultsCollected; - public ExceptionPropertiesBag(Exception exception, IExceptionPropertyFilter filter = null) + public ExceptionPropertiesBag(Exception exception, IExceptionPropertyFilter? filter = null) { this.exception = exception ?? throw new ArgumentNullException(nameof(exception)); this.filter = filter; } - public IReadOnlyDictionary GetResultDictionary() + public IReadOnlyDictionary GetResultDictionary() { this.resultsCollected = true; return this.properties; } - public void AddProperty(string key, object value) + public void AddProperty(string key, object? value) { if (key is null) { diff --git a/Directory.Build.props b/Directory.Build.props index 52c3720c..8e2248ba 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,6 +4,7 @@ latest true latest + enable en-GB true diff --git a/Source/Serilog.Exceptions.EntityFrameworkCore/Destructurers/DbUpdateExceptionDestructurer.cs b/Source/Serilog.Exceptions.EntityFrameworkCore/Destructurers/DbUpdateExceptionDestructurer.cs index b0f07563..7db2447e 100644 --- a/Source/Serilog.Exceptions.EntityFrameworkCore/Destructurers/DbUpdateExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions.EntityFrameworkCore/Destructurers/DbUpdateExceptionDestructurer.cs @@ -20,7 +20,7 @@ public class DbUpdateExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions.MsSqlServer/Destructurers/SqlExceptionDestructurer.cs b/Source/Serilog.Exceptions.MsSqlServer/Destructurers/SqlExceptionDestructurer.cs index 18ec990b..1bcf4925 100644 --- a/Source/Serilog.Exceptions.MsSqlServer/Destructurers/SqlExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions.MsSqlServer/Destructurers/SqlExceptionDestructurer.cs @@ -20,7 +20,7 @@ public class SqlExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions.SqlServer/Destructurers/SqlExceptionDestructurer.cs b/Source/Serilog.Exceptions.SqlServer/Destructurers/SqlExceptionDestructurer.cs index 71568d8d..3a8de991 100644 --- a/Source/Serilog.Exceptions.SqlServer/Destructurers/SqlExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions.SqlServer/Destructurers/SqlExceptionDestructurer.cs @@ -20,7 +20,7 @@ public class SqlExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); @@ -36,4 +36,4 @@ public override void Destructure( #pragma warning restore CA1062 // Validate arguments of public methods } } -} \ No newline at end of file +} diff --git a/Source/Serilog.Exceptions/Core/DestructuringOptionsBuilder.cs b/Source/Serilog.Exceptions/Core/DestructuringOptionsBuilder.cs index 7dbee3ef..64304b34 100644 --- a/Source/Serilog.Exceptions/Core/DestructuringOptionsBuilder.cs +++ b/Source/Serilog.Exceptions/Core/DestructuringOptionsBuilder.cs @@ -67,7 +67,7 @@ public class DestructuringOptionsBuilder : IDestructuringOptions /// /// Gets a global filter, that will be applied to every destructured property just before it is added to the result. /// - public IExceptionPropertyFilter Filter { get; private set; } + public IExceptionPropertyFilter? Filter { get; private set; } /// /// Accumulates destructurers to be used by . diff --git a/Source/Serilog.Exceptions/Core/ExceptionEnricher.cs b/Source/Serilog.Exceptions/Core/ExceptionEnricher.cs index acafc33c..e50d430d 100644 --- a/Source/Serilog.Exceptions/Core/ExceptionEnricher.cs +++ b/Source/Serilog.Exceptions/Core/ExceptionEnricher.cs @@ -74,7 +74,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) } } - private IReadOnlyDictionary DestructureException(Exception exception) + private IReadOnlyDictionary? DestructureException(Exception exception) { var exceptionType = exception.GetType(); diff --git a/Source/Serilog.Exceptions/Core/ExceptionPropertiesBag.cs b/Source/Serilog.Exceptions/Core/ExceptionPropertiesBag.cs index 16dfdb26..84db0002 100644 --- a/Source/Serilog.Exceptions/Core/ExceptionPropertiesBag.cs +++ b/Source/Serilog.Exceptions/Core/ExceptionPropertiesBag.cs @@ -8,8 +8,8 @@ namespace Serilog.Exceptions.Core internal class ExceptionPropertiesBag : IExceptionPropertiesBag { private readonly Exception exception; - private readonly IExceptionPropertyFilter filter; - private readonly Dictionary properties = new(); + private readonly IExceptionPropertyFilter? filter; + private readonly Dictionary properties = new(); /// /// We keep a note on whether the results were collected to be sure that after that there are no changes. This @@ -22,21 +22,21 @@ internal class ExceptionPropertiesBag : IExceptionPropertiesBag /// /// The exception which properties will be added to the bag. /// Filter that should be applied to each property just before adding it to the bag. - public ExceptionPropertiesBag(Exception exception, IExceptionPropertyFilter filter = null) + public ExceptionPropertiesBag(Exception exception, IExceptionPropertyFilter? filter = null) { this.exception = exception ?? throw new ArgumentNullException(nameof(exception)); this.filter = filter; } /// - public IReadOnlyDictionary GetResultDictionary() + public IReadOnlyDictionary GetResultDictionary() { this.resultsCollected = true; return this.properties; } /// - public void AddProperty(string key, object value) + public void AddProperty(string key, object? value) { if (key is null) { diff --git a/Source/Serilog.Exceptions/Core/IDestructuringOptions.cs b/Source/Serilog.Exceptions/Core/IDestructuringOptions.cs index c4a2f5cd..fc0063ba 100644 --- a/Source/Serilog.Exceptions/Core/IDestructuringOptions.cs +++ b/Source/Serilog.Exceptions/Core/IDestructuringOptions.cs @@ -1,44 +1,44 @@ -namespace Serilog.Exceptions.Core -{ - using System.Collections.Generic; - using Serilog.Exceptions.Destructurers; - using Serilog.Exceptions.Filters; - - /// - /// Represents all the configuration options user can specify to influence the destructuring process. - /// - public interface IDestructuringOptions - { - /// +namespace Serilog.Exceptions.Core +{ + using System.Collections.Generic; + using Serilog.Exceptions.Destructurers; + using Serilog.Exceptions.Filters; + + /// + /// Represents all the configuration options user can specify to influence the destructuring process. + /// + public interface IDestructuringOptions + { + /// /// Gets the name of the key dictionary to which destructured exception will be assigned. Default is - /// "ExceptionDetail". - /// - string RootName { get; } - - /// - /// Gets the depth at which reflection based destructurer will stop recursive process of children destructuring. - /// Default is 10. - /// - int DestructuringDepth { get; } - - /// - /// Gets the collection of destructurers that will be used to destructure incoming exceptions. If none of the - /// destructurers can handle given type of exception, a generic, reflection-based destructurer will be used. - /// - IEnumerable Destructurers { get; } - - /// - /// Gets the optional filter that will evaluate and possibly reject each destructured property just before - /// they are about to be written to a result structure. If no filter is set no properties are going to be - /// rejected. Filter is applied to every property regardless of which destructurer was used. - /// - IExceptionPropertyFilter Filter { get; } - + /// "ExceptionDetail". + /// + string RootName { get; } + + /// + /// Gets the depth at which reflection based destructurer will stop recursive process of children destructuring. + /// Default is 10. + /// + int DestructuringDepth { get; } + + /// + /// Gets the collection of destructurers that will be used to destructure incoming exceptions. If none of the + /// destructurers can handle given type of exception, a generic, reflection-based destructurer will be used. + /// + IEnumerable Destructurers { get; } + + /// + /// Gets the optional filter that will evaluate and possibly reject each destructured property just before + /// they are about to be written to a result structure. If no filter is set no properties are going to be + /// rejected. Filter is applied to every property regardless of which destructurer was used. + /// + IExceptionPropertyFilter? Filter { get; } + /// - /// Gets a value indicating whether to disable the reflection based destructurer. - /// You may want to disable this destructurer if you need full control + /// Gets a value indicating whether to disable the reflection based destructurer. + /// You may want to disable this destructurer if you need full control /// over the process of destructuring and want to provide all the destructurers yourself. - /// - bool DisableReflectionBasedDestructurer { get; } - } -} + /// + bool DisableReflectionBasedDestructurer { get; } + } +} diff --git a/Source/Serilog.Exceptions/Core/IExceptionPropertiesBag.cs b/Source/Serilog.Exceptions/Core/IExceptionPropertiesBag.cs index 5215ffc1..42772325 100644 --- a/Source/Serilog.Exceptions/Core/IExceptionPropertiesBag.cs +++ b/Source/Serilog.Exceptions/Core/IExceptionPropertiesBag.cs @@ -13,14 +13,14 @@ public interface IExceptionPropertiesBag /// method. /// /// Dictionary with all the properties names and values that were added. - IReadOnlyDictionary GetResultDictionary(); + IReadOnlyDictionary GetResultDictionary(); /// /// Adds a property to the bag. /// /// The key. /// The value. - void AddProperty(string key, object value); + void AddProperty(string key, object? value); /// /// Returns true if given key is already present in the bag. diff --git a/Source/Serilog.Exceptions/Destructurers/AggregateExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/AggregateExceptionDestructurer.cs index a2d49d67..b7c0cf92 100644 --- a/Source/Serilog.Exceptions/Destructurers/AggregateExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/AggregateExceptionDestructurer.cs @@ -17,7 +17,7 @@ public class AggregateExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions/Destructurers/ArgumentExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/ArgumentExceptionDestructurer.cs index 9c33a5d9..065de1a6 100644 --- a/Source/Serilog.Exceptions/Destructurers/ArgumentExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/ArgumentExceptionDestructurer.cs @@ -20,7 +20,7 @@ public class ArgumentExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions/Destructurers/ArgumentOutOfRangeExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/ArgumentOutOfRangeExceptionDestructurer.cs index 1a1f79d2..d5716a20 100644 --- a/Source/Serilog.Exceptions/Destructurers/ArgumentOutOfRangeExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/ArgumentOutOfRangeExceptionDestructurer.cs @@ -19,7 +19,7 @@ public class ArgumentOutOfRangeExceptionDestructurer : ArgumentExceptionDestruct public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions/Destructurers/ExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/ExceptionDestructurer.cs index 75d91b30..494a9170 100644 --- a/Source/Serilog.Exceptions/Destructurers/ExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/ExceptionDestructurer.cs @@ -22,6 +22,7 @@ public virtual Type[] TargetTypes { var targetTypes = new List { +#pragma warning disable IDE0001 // Simplify Names #if NET461 || NET472 typeof(Microsoft.SqlServer.Server.InvalidUdtException), typeof(System.AccessViolationException), @@ -174,6 +175,7 @@ public virtual Type[] TargetTypes typeof(System.UnauthorizedAccessException), typeof(System.UriFormatException), }; +#pragma warning restore IDE0001 // Simplify Names #if NET461 || NET472 foreach (var dangerousType in GetNotHandledByMonoTypes()) @@ -193,7 +195,7 @@ public virtual Type[] TargetTypes public virtual void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { if (exception is null) { @@ -230,7 +232,7 @@ public virtual void Destructure( internal static void DestructureCommonExceptionProperties( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> innerDestructure, + Func?> innerDestructure, Func destructureDataProperty) { if (exception.Data.Count != 0) diff --git a/Source/Serilog.Exceptions/Destructurers/IExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/IExceptionDestructurer.cs index 7ab956b5..ced4a8d0 100644 --- a/Source/Serilog.Exceptions/Destructurers/IExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/IExceptionDestructurer.cs @@ -28,6 +28,6 @@ public interface IExceptionDestructurer void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException); + Func?> destructureException); } } diff --git a/Source/Serilog.Exceptions/Destructurers/OperationCanceledExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/OperationCanceledExceptionDestructurer.cs index 87ce8c87..a09dcce9 100644 --- a/Source/Serilog.Exceptions/Destructurers/OperationCanceledExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/OperationCanceledExceptionDestructurer.cs @@ -25,7 +25,7 @@ public class OperationCanceledExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions/Destructurers/ReflectionBasedDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/ReflectionBasedDestructurer.cs index 30fd777f..31dc2aa5 100644 --- a/Source/Serilog.Exceptions/Destructurers/ReflectionBasedDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/ReflectionBasedDestructurer.cs @@ -56,7 +56,7 @@ public ReflectionBasedDestructurer(int destructuringDepth) public void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { if (exception is null) { @@ -74,7 +74,7 @@ public void Destructure( } var nextCyclicRefId = 1; - var destructuredObjects = new Dictionary>(); + var destructuredObjects = new Dictionary>(); ExceptionDestructurer.DestructureCommonExceptionProperties( exception, @@ -95,12 +95,12 @@ public void Destructure( AppendTypeIfPossible(propertiesBag, exception.GetType()); } - private static string GetOrGenerateRefId(ref int nextCyclicRefId, IDictionary destructuredObject) + private static string? GetOrGenerateRefId(ref int nextCyclicRefId, IDictionary destructuredObject) { - string refId; + string? refId; if (destructuredObject.ContainsKey(IdLabel)) { - refId = (string)destructuredObject[IdLabel]; + refId = (string?)destructuredObject[IdLabel]; } else { @@ -154,8 +154,8 @@ private static void AppendTypeIfPossible(IExceptionPropertiesBag propertiesBag, private void AppendProperties( object value, ReflectionPropertyInfo[] reflectionPropertyInfos, - Action addPropertyAction, - IDictionary> destructuredObjects, + Action addPropertyAction, + IDictionary> destructuredObjects, int level, ref int nextCyclicRefId) { @@ -193,28 +193,20 @@ private void AppendProperties( private ReflectionInfo GenerateReflectionInfoForType(Type valueType) { var properties = GetExceptionPropertiesForDestructuring(valueType); - var propertyInfos = properties.Select(p => new ReflectionPropertyInfo() - { - Name = p.Name, - DeclaringType = p.DeclaringType, - Getter = GenerateFastGetterForProperty(valueType, p), - }).ToArray(); + var propertyInfos = properties + .Select(p => new ReflectionPropertyInfo(p.Name, p.DeclaringType, GenerateFastGetterForProperty(valueType, p))) + .ToArray(); var propertiesInfosExceptBaseOnes = propertyInfos .Where(p => this.baseExceptionPropertiesForDestructuring.All(bp => bp.Name != p.Name)) .ToArray(); - var reflectionInfo = new ReflectionInfo() - { - Properties = propertyInfos, - PropertiesExceptBaseOnes = propertiesInfosExceptBaseOnes, - }; - return reflectionInfo; + return new ReflectionInfo(propertyInfos, propertiesInfosExceptBaseOnes); } - private object DestructureValue( - object value, + private object? DestructureValue( + object? value, int level, - IDictionary> destructuredObjects, + IDictionary> destructuredObjects, ref int nextCyclicRefId) { if (value is null) @@ -271,7 +263,7 @@ private object DestructureValue( private object DestructureValueEnumerable( IEnumerable value, int level, - IDictionary> destructuredObjects, + IDictionary> destructuredObjects, ref int nextCyclicRefId) { if (destructuredObjects.ContainsKey(value)) @@ -282,9 +274,9 @@ private object DestructureValueEnumerable( }; } - destructuredObjects.Add(value, new Dictionary()); + destructuredObjects.Add(value, new Dictionary()); - var resultList = new List(); + var resultList = new List(); foreach (var o in value.Cast()) { resultList.Add(this.DestructureValue(o, level + 1, destructuredObjects, ref nextCyclicRefId)); @@ -296,7 +288,7 @@ private object DestructureValueEnumerable( private object DestructureValueDictionary( IDictionary value, int level, - IDictionary> destructuredObjects, + IDictionary> destructuredObjects, ref int nextCyclicRefId) { if (destructuredObjects.ContainsKey(value)) @@ -304,7 +296,7 @@ private object DestructureValueDictionary( var destructuredObject = destructuredObjects[value]; var refId = GetOrGenerateRefId(ref nextCyclicRefId, destructuredObject); - return new Dictionary + return new Dictionary { { RefLabel, refId }, }; @@ -322,11 +314,11 @@ private object DestructureValueDictionary( return destructuredDictionary; } - private IDictionary DestructureObject( + private IDictionary DestructureObject( object value, Type valueType, int level, - IDictionary> destructuredObjects, + IDictionary> destructuredObjects, ref int nextCyclicRefId) { if (destructuredObjects.ContainsKey(value)) @@ -334,13 +326,13 @@ private IDictionary DestructureObject( var destructuredObject = destructuredObjects[value]; var refId = GetOrGenerateRefId(ref nextCyclicRefId, destructuredObject); - return new Dictionary() + return new Dictionary() { { RefLabel, refId }, }; } - var values = new Dictionary(); + var values = new Dictionary(); destructuredObjects.Add(value, values); var reflectionInfo = this.GetOrCreateReflectionInfo(valueType); @@ -355,7 +347,7 @@ private IDictionary DestructureObject( level + 1, destructuredObjects, ref nextCyclicRefId); - var key = values.ContainsKey(property.Name) ? $"{property.DeclaringType.FullName}.{property.Name}" : property.Name; + var key = values.ContainsKey(property.Name) ? $"{property.DeclaringType?.FullName}.{property.Name}" : property.Name; values.Add(key, destructuredValue); } catch (TargetInvocationException targetInvocationException) @@ -380,20 +372,20 @@ private IDictionary DestructureObject( private object DestructureTask( Task task, int level, - IDictionary> destructuredObjects, + IDictionary> destructuredObjects, ref int nextCyclicRefId) { if (destructuredObjects.TryGetValue(task, out var destructuredTask)) { var refId = GetOrGenerateRefId(ref nextCyclicRefId, destructuredTask); - return new SortedList() + return new SortedList() { { RefLabel, refId }, }; } - var values = new SortedList(); + var values = new SortedList(); destructuredObjects.Add(task, values); values[nameof(Task.Id)] = task.Id; @@ -423,18 +415,31 @@ private ReflectionInfo GetOrCreateReflectionInfo(Type valueType) private class ReflectionInfo { - public ReflectionPropertyInfo[] Properties { get; set; } + public ReflectionInfo(ReflectionPropertyInfo[] properties, ReflectionPropertyInfo[] propertiesExceptBaseOnes) + { + this.Properties = properties; + this.PropertiesExceptBaseOnes = propertiesExceptBaseOnes; + } + + public ReflectionPropertyInfo[] Properties { get; } - public ReflectionPropertyInfo[] PropertiesExceptBaseOnes { get; set; } + public ReflectionPropertyInfo[] PropertiesExceptBaseOnes { get; } } private class ReflectionPropertyInfo { - public string Name { get; set; } + public ReflectionPropertyInfo(string name, Type? declaringType, Func getter) + { + this.Name = name; + this.DeclaringType = declaringType; + this.Getter = getter; + } + + public string Name { get; } - public Type DeclaringType { get; set; } + public Type? DeclaringType { get; } - public Func Getter { get; set; } + public Func Getter { get; } } } } diff --git a/Source/Serilog.Exceptions/Destructurers/ReflectionTypeLoadExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/ReflectionTypeLoadExceptionDestructurer.cs index 82407c46..d99d4529 100644 --- a/Source/Serilog.Exceptions/Destructurers/ReflectionTypeLoadExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/ReflectionTypeLoadExceptionDestructurer.cs @@ -2,7 +2,6 @@ namespace Serilog.Exceptions.Destructurers { using System; using System.Collections.Generic; - using System.Linq; using System.Reflection; using Serilog.Exceptions.Core; @@ -18,7 +17,7 @@ public class ReflectionTypeLoadExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); @@ -28,9 +27,29 @@ public override void Destructure( { propertiesBag.AddProperty( nameof(ReflectionTypeLoadException.LoaderExceptions), - reflectionTypeLoadException.LoaderExceptions.Select(destructureException).ToList()); + GetLoaderExceptionsValue(reflectionTypeLoadException.LoaderExceptions, destructureException)); } #pragma warning restore CA1062 // Validate arguments of public methods } + + private static List> GetLoaderExceptionsValue( + Exception?[] exceptions, + Func?> destructureException) + { + var loaderExceptionValues = new List>(); + foreach (var exception in exceptions) + { + if (exception is not null) + { + var dictionary = destructureException(exception); + if (dictionary is not null) + { + loaderExceptionValues.Add(dictionary); + } + } + } + + return loaderExceptionValues; + } } } diff --git a/Source/Serilog.Exceptions/Destructurers/SocketExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/SocketExceptionDestructurer.cs index e87b1633..7ac3d4a6 100644 --- a/Source/Serilog.Exceptions/Destructurers/SocketExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/SocketExceptionDestructurer.cs @@ -73,7 +73,7 @@ public class SocketExceptionDestructurer : ExceptionDestructurer public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { base.Destructure(exception, propertiesBag, destructureException); diff --git a/Source/Serilog.Exceptions/Destructurers/TaskCanceledExceptionDestructurer.cs b/Source/Serilog.Exceptions/Destructurers/TaskCanceledExceptionDestructurer.cs index b9ca34ab..06f7134d 100644 --- a/Source/Serilog.Exceptions/Destructurers/TaskCanceledExceptionDestructurer.cs +++ b/Source/Serilog.Exceptions/Destructurers/TaskCanceledExceptionDestructurer.cs @@ -22,7 +22,7 @@ public class TaskCanceledExceptionDestructurer : OperationCanceledExceptionDestr public override void Destructure( Exception exception, IExceptionPropertiesBag propertiesBag, - Func> destructureException) + Func?> destructureException) { #pragma warning disable CA1062 // Validate arguments of public methods base.Destructure(exception, propertiesBag, destructureException); @@ -41,8 +41,8 @@ public override void Destructure( /// The inner destructure. /// The destructured task. internal static object DestructureTask( - Task task, - Func> innerDestructure) + Task? task, + Func?> innerDestructure) { if (task is null) { diff --git a/Source/Serilog.Exceptions/DictionaryExtensions.cs b/Source/Serilog.Exceptions/DictionaryExtensions.cs index 3c3bfd4a..408e7b46 100644 --- a/Source/Serilog.Exceptions/DictionaryExtensions.cs +++ b/Source/Serilog.Exceptions/DictionaryExtensions.cs @@ -13,15 +13,22 @@ internal static class DictionaryExtensions /// /// The input dictionary. /// A dictionary with string-ified keys. - public static Dictionary ToStringObjectDictionary(this IDictionary dictionary) + public static Dictionary ToStringObjectDictionary(this IDictionary dictionary) { - var result = new Dictionary(dictionary.Count); + var result = new Dictionary(dictionary.Count); foreach (var key in dictionary.Keys) { - var value = dictionary[key]; + if (key is not null) + { + var keyString = key.ToString(); + var value = dictionary[key]; - result.Add(key.ToString(), value); + if (keyString is not null) + { + result.Add(keyString, value); + } + } } return result; diff --git a/Source/Serilog.Exceptions/Filters/CompositeExceptionPropertyFilter.cs b/Source/Serilog.Exceptions/Filters/CompositeExceptionPropertyFilter.cs index 87226217..88a8d680 100644 --- a/Source/Serilog.Exceptions/Filters/CompositeExceptionPropertyFilter.cs +++ b/Source/Serilog.Exceptions/Filters/CompositeExceptionPropertyFilter.cs @@ -43,7 +43,7 @@ public CompositeExceptionPropertyFilter(params IExceptionPropertyFilter[] filter } /// - public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object value) + public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value) { for (var i = 0; i < this.filters.Length; ++i) { diff --git a/Source/Serilog.Exceptions/Filters/IExceptionPropertyFilter.cs b/Source/Serilog.Exceptions/Filters/IExceptionPropertyFilter.cs index de0ef408..a43e92c7 100644 --- a/Source/Serilog.Exceptions/Filters/IExceptionPropertyFilter.cs +++ b/Source/Serilog.Exceptions/Filters/IExceptionPropertyFilter.cs @@ -15,6 +15,6 @@ public interface IExceptionPropertyFilter /// Name of the property. /// Destructured value of the property. /// Boolean flag indicating whether property will be rejected. - bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object value); + bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value); } } diff --git a/Source/Serilog.Exceptions/Filters/IgnorePropertyByNameExceptionFilter.cs b/Source/Serilog.Exceptions/Filters/IgnorePropertyByNameExceptionFilter.cs index 4f57eb0e..5fc1a21f 100644 --- a/Source/Serilog.Exceptions/Filters/IgnorePropertyByNameExceptionFilter.cs +++ b/Source/Serilog.Exceptions/Filters/IgnorePropertyByNameExceptionFilter.cs @@ -23,7 +23,7 @@ public IgnorePropertyByNameExceptionFilter(params string[] propertiesToIgnore) = this.propertiesToIgnore = propertiesToIgnore; /// - public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object value) + public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value) { if (this.propertiesToIgnore is null) { @@ -41,4 +41,4 @@ public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, o return false; } } -} \ No newline at end of file +} diff --git a/Tests/Serilog.Exceptions.Test/Destructurers/DbUpdateExceptionDestructurerTest.cs b/Tests/Serilog.Exceptions.Test/Destructurers/DbUpdateExceptionDestructurerTest.cs index 3665c0c0..f9e5b557 100644 --- a/Tests/Serilog.Exceptions.Test/Destructurers/DbUpdateExceptionDestructurerTest.cs +++ b/Tests/Serilog.Exceptions.Test/Destructurers/DbUpdateExceptionDestructurerTest.cs @@ -67,14 +67,14 @@ public void WithDbUpdateExceptionDestructurerShouldNotLogDbValues() internal class User { - public string UserId { get; set; } + public string? UserId { get; set; } } internal class TestContext : DbContext { public const string UserIdIDoNotWantToSee = "I Don't Want To See You"; - public DbSet Users { get; set; } + public DbSet? Users { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseInMemoryDatabase(databaseName: "TestDebUpdateException"); @@ -101,7 +101,7 @@ internal class TestDbUpdateException : DbUpdateException private readonly IReadOnlyList entityEntries; public TestDbUpdateException(string message, EntityEntry entityEntry) - : base(message, (Exception)null) => this.entityEntries = new List { entityEntry }.AsReadOnly(); + : base(message, (Exception)null!) => this.entityEntries = new List { entityEntry }.AsReadOnly(); public override IReadOnlyList Entries => this.entityEntries; } diff --git a/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionDestructurerTest.cs b/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionDestructurerTest.cs index dea81085..75582b73 100644 --- a/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionDestructurerTest.cs +++ b/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionDestructurerTest.cs @@ -73,7 +73,7 @@ public void ArgumentException_ContainsSource() public void ArgumentException_WithoutStackTrace_ContainsNullStackTrace() { var applicationException = new ArgumentException(); - Test_LoggedExceptionContainsProperty(applicationException, "StackTrace", null); + Test_LoggedExceptionContainsProperty(applicationException, "StackTrace", null!); } [Fact] @@ -164,7 +164,7 @@ public void ArgumentException_WithStackTrace_ContainsStackTrace() } catch (ArgumentException ex) { - Test_LoggedExceptionContainsProperty(ex, "StackTrace", ex.StackTrace.ToString(CultureInfo.InvariantCulture)); + Test_LoggedExceptionContainsProperty(ex, "StackTrace", ex.StackTrace?.ToString(CultureInfo.InvariantCulture)); } } diff --git a/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionPropertiesBagTest.cs b/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionPropertiesBagTest.cs index 7acc5b23..d8ffbc95 100644 --- a/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionPropertiesBagTest.cs +++ b/Tests/Serilog.Exceptions.Test/Destructurers/ExceptionPropertiesBagTest.cs @@ -11,7 +11,7 @@ public class ExceptionPropertiesBagTest public void Constructor_GivenNullException_Throws() { // Act - var ex = Assert.Throws(() => new ExceptionPropertiesBag(null)); + var ex = Assert.Throws(() => new ExceptionPropertiesBag(null!)); // Assert Assert.Equal("exception", ex.ParamName); @@ -56,7 +56,7 @@ public void CannotAddProperty_WhenKeyIsNull() var properties = new ExceptionPropertiesBag(new Exception(), null); // Act - var ex = Assert.Throws(() => properties.AddProperty(null, "value")); + var ex = Assert.Throws(() => properties.AddProperty(null!, "value")); // Assert Assert.Equal("key", ex.ParamName); diff --git a/Tests/Serilog.Exceptions.Test/Destructurers/LogJsonOutputUtils.cs b/Tests/Serilog.Exceptions.Test/Destructurers/LogJsonOutputUtils.cs index b0c03c65..172818a2 100644 --- a/Tests/Serilog.Exceptions.Test/Destructurers/LogJsonOutputUtils.cs +++ b/Tests/Serilog.Exceptions.Test/Destructurers/LogJsonOutputUtils.cs @@ -16,7 +16,7 @@ public static class LogJsonOutputUtils { public static JObject LogAndDestructureException( Exception exception, - IDestructuringOptions destructuringOptions = null) + IDestructuringOptions? destructuringOptions = null) { // Arrange var jsonWriter = new StringWriter(); @@ -36,7 +36,7 @@ public static JObject LogAndDestructureException( return rootObject; } - public static void Test_LoggedExceptionContainsProperty(Exception exception, string propertyKey, string propertyValue) + public static void Test_LoggedExceptionContainsProperty(Exception exception, string propertyKey, string? propertyValue) { var rootObject = LogAndDestructureException(exception); Assert_JObjectContainsPropertiesExceptionDetailsWithProperty(rootObject, propertyKey, propertyValue); @@ -83,7 +83,7 @@ public static JObject ExtractPropertiesObject(JObject rootObject) public static void Assert_ContainsPropertyWithValue( JObject jObject, string propertyKey, - string propertyValue) + string? propertyValue) { var paramNameProperty = ExtractProperty(jObject, propertyKey); var paramName = Assert.IsType(paramNameProperty.Value); @@ -123,7 +123,7 @@ public static JProperty ExtractProperty(JObject jObject, string propertyKey) public static void Assert_JObjectContainsPropertiesExceptionDetailsWithProperty( JObject jObject, string propertyKey, - string propertyValue) + string? propertyValue) { var exceptionDetailValue = ExtractExceptionDetails(jObject); Assert_ContainsPropertyWithValue(exceptionDetailValue, propertyKey, propertyValue); diff --git a/Tests/Serilog.Exceptions.Test/Destructurers/ReflectionBasedDestructurerTest.cs b/Tests/Serilog.Exceptions.Test/Destructurers/ReflectionBasedDestructurerTest.cs index 0167a844..74e95b3f 100644 --- a/Tests/Serilog.Exceptions.Test/Destructurers/ReflectionBasedDestructurerTest.cs +++ b/Tests/Serilog.Exceptions.Test/Destructurers/ReflectionBasedDestructurerTest.cs @@ -34,10 +34,10 @@ public void DestructureComplexException_EachTypeOfPropertyIsDestructuredAsExpect #if NET461 || NET472 Assert.StartsWith("Void DestructureComplexException_EachTypeOfPropertyIsDestructuredAsExpected(", properties[nameof(TestException.TargetSite)].ToString()); #endif - Assert.NotEmpty(properties[nameof(TestException.StackTrace)].ToString()); + Assert.NotEmpty(properties[nameof(TestException.StackTrace)]?.ToString()); Assert.Equal("Serilog.Exceptions.Test", properties[nameof(TestException.Source)]); Assert.Equal(-2146233088, properties[nameof(TestException.HResult)]); - Assert.Contains(typeof(TestException).FullName, properties["Type"].ToString(), StringComparison.Ordinal); + Assert.Contains(typeof(TestException).FullName, properties["Type"]?.ToString(), StringComparison.Ordinal); } [Fact] @@ -71,8 +71,8 @@ public void CanDestructureUriDataItem() CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); - var data = (IDictionary)properties[nameof(Exception.Data)]; - var uriDataValue = data["UriDataItem"]; + var data = (IDictionary?)properties[nameof(Exception.Data)]; + var uriDataValue = data?["UriDataItem"]; Assert.IsType(uriDataValue); Assert.Equal(uriValue, uriDataValue); } @@ -82,10 +82,12 @@ public async Task CanDestructureTaskAsync() { using var cancellationTokenSource = new CancellationTokenSource(0); - TaskCanceledException exception = null; + TaskCanceledException exception; try { await Task.Delay(1000, cancellationTokenSource.Token).ConfigureAwait(false); + Assert.True(false, "TaskCanceledException was not thrown."); + return; } catch (TaskCanceledException taskCancelledException) { @@ -96,7 +98,7 @@ public async Task CanDestructureTaskAsync() CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, EmptyDestructurer()); var properties = propertiesBag.GetResultDictionary(); - var destructuredTaskObject = (IDictionary)properties[nameof(TaskCanceledException.Task)]; + var destructuredTaskObject = (IDictionary?)properties[nameof(TaskCanceledException.Task)]; var destructuredTaskProperties = Assert.IsAssignableFrom>(destructuredTaskObject); destructuredTaskProperties.Should().ContainKey(nameof(Task.Id)); destructuredTaskProperties.Should().ContainKey(nameof(Task.Status)) @@ -118,7 +120,7 @@ public void CanDestructureFaultedTask() CreateReflectionBasedDestructurer().Destructure(exception, propertiesBag, InnerDestructurer(CreateReflectionBasedDestructurer())); var properties = propertiesBag.GetResultDictionary(); - var destructuredTaskObject = (IDictionary)properties[nameof(TaskCanceledException.Task)]; + var destructuredTaskObject = (IDictionary?)properties[nameof(TaskCanceledException.Task)]; var destructuredTaskProperties = Assert.IsAssignableFrom>(destructuredTaskObject); destructuredTaskProperties.Should().ContainKey(nameof(Task.Id)); destructuredTaskProperties.Should().ContainKey(nameof(Task.Status)) @@ -159,8 +161,8 @@ public void CanDestructureStructDataItem() // Assert var properties = propertiesBag.GetResultDictionary(); - var data = (IDictionary)properties[nameof(Exception.Data)]; - var testStructDataValue = data["data"]; + var data = (IDictionary?)properties[nameof(Exception.Data)]; + var testStructDataValue = data?["data"]; Assert.IsAssignableFrom(testStructDataValue); } @@ -181,8 +183,8 @@ public void CanDestructureClassDataItem() // Assert var properties = propertiesBag.GetResultDictionary(); - var data = (IDictionary)properties[nameof(Exception.Data)]; - var testStructDataValue = data["data"]; + var data = (IDictionary?)properties[nameof(Exception.Data)]; + var testStructDataValue = data?["data"]; var destructuredStructDictionary = Assert.IsAssignableFrom>(testStructDataValue); Assert.Equal(10, destructuredStructDictionary[nameof(TestClass.ValueType)]); Assert.Equal("ABC", destructuredStructDictionary[nameof(TestClass.ReferenceType)]); @@ -217,9 +219,9 @@ public void DestructuringDepthIsLimitedByConfiguredDepth() // Parent is depth 1 // First child is depth 2 var properties = propertiesBag.GetResultDictionary(); - var parent = (IDictionary)properties[nameof(RecursiveException.Node)]; - Assert.Equal("PARENT", parent[nameof(RecursiveNode.Name)]); - Assert.IsType(parent[nameof(RecursiveNode.Child)]); + var parent = (IDictionary?)properties[nameof(RecursiveException.Node)]; + Assert.Equal("PARENT", parent?[nameof(RecursiveNode.Name)]); + Assert.IsType(parent?[nameof(RecursiveNode.Child)]); } [Fact] @@ -247,12 +249,14 @@ public void WhenObjectContainsCyclicReferences_ThenNoStackoverflowExceptionIsThr destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert - var myObject = (Dictionary)result.GetResultDictionary()["MyObject"]; + var myObject = (Dictionary?)result.GetResultDictionary()["MyObject"]; - Assert.Equal("bar", myObject["Foo"]); - Assert.Equal(myObject["$id"], ((Dictionary)myObject["Reference"])["$ref"]); - Assert.Equal(myObject["$id"], ((Dictionary)myObject["Reference2"])["$ref"]); - Assert.Equal("1", myObject["$id"]); + Assert.Equal("bar", myObject?["Foo"]); + var reference1 = (Dictionary?)myObject?["Reference"]; + Assert.Equal(myObject?["$id"], reference1?["$ref"]); + var reference2 = (Dictionary?)myObject?["Reference2"]; + Assert.Equal(myObject?["$id"], reference2?["$ref"]); + Assert.Equal("1", myObject?["$id"]); } [Fact] @@ -277,10 +281,10 @@ public void WhenObjectContainsCyclicReferencesInList_ThenRecursiveDestructureIsI destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert - var myObject = (List)result.GetResultDictionary()[nameof(Cyclic2Exception.MyObjectCollection)]; + var myObject = (List?)result.GetResultDictionary()[nameof(Cyclic2Exception.MyObjectCollection)]; // exception.MyObjectCollection[0] is still list - var firstLevelList = Assert.IsType>(myObject[0]); + var firstLevelList = Assert.IsType>(myObject?[0]); // exception.MyObjectCollection[0][0] we notice that we would again destructure "cyclic" var secondLevelList = Assert.IsType>(firstLevelList[0]); @@ -308,10 +312,10 @@ public void WhenObjectContainsCyclicReferencesInDict_ThenRecursiveDestructureIsI destructurer.Destructure(exception, result, EmptyDestructurer()); // Assert - var myObject = (Dictionary)result.GetResultDictionary()["MyObjectDict"]; + var myObject = (Dictionary?)result.GetResultDictionary()["MyObjectDict"]; // exception.MyObjectDict["Reference"] is still regular dictionary - var firstLevelDict = Assert.IsType>(myObject["Reference"]); + var firstLevelDict = Assert.IsType>(myObject?["Reference"]); var id = firstLevelDict["$id"]; Assert.Equal("1", id); @@ -376,8 +380,8 @@ public void CanDestructureObjectWithHiddenProperty() var properties = propertiesBag.GetResultDictionary(); var info = properties[nameof(HiddenException.Info)] as IDictionary; - Assert.Equal(derived.HiddenProperty, info[nameof(DerivedClass.HiddenProperty)]); - Assert.Equal(baseClass.HiddenProperty, info[$"{typeof(BaseClass).FullName}.{nameof(BaseClass.HiddenProperty)}"]); + Assert.Equal(derived.HiddenProperty, info?[nameof(DerivedClass.HiddenProperty)]); + Assert.Equal(baseClass.HiddenProperty, info?[$"{typeof(BaseClass).FullName}.{nameof(BaseClass.HiddenProperty)}"]); } private static void Test_ResultOfReflectionDestructurerShouldBeEquivalentToCustomOne( @@ -400,10 +404,10 @@ private static void Test_ResultOfReflectionDestructurerShouldBeEquivalentToCusto reflectionBasedDictionary.Should().BeEquivalentTo(customBasedDictionary); } - private static Func> EmptyDestructurer() => + private static Func> EmptyDestructurer() => (ex) => new ExceptionPropertiesBag(ex).GetResultDictionary(); - private static Func> InnerDestructurer( + private static Func?> InnerDestructurer( IExceptionDestructurer destructurer) => (ex) => { @@ -428,7 +432,7 @@ private static Exception ThrowAndCatchException(Action throwingAction) } Assert.True(false, $"{nameof(throwingAction)} did not throw"); - return null; + return null!; // We should never reach this line. } private static ReflectionBasedDestructurer CreateReflectionBasedDestructurer() => @@ -436,58 +440,58 @@ private static ReflectionBasedDestructurer CreateReflectionBasedDestructurer() = public class MyObject { - public string Foo { get; set; } + public string? Foo { get; set; } - public MyObject Reference { get; set; } + public MyObject? Reference { get; set; } - public MyObject Reference2 { get; set; } + public MyObject? Reference2 { get; set; } } public class CyclicException : Exception { - public MyObject MyObject { get; set; } + public MyObject? MyObject { get; set; } } public class MyObjectCollection : IEnumerable { - public string Foo { get; set; } + public string? Foo { get; set; } - public MyObjectCollection Reference { get; set; } + public MyObjectCollection? Reference { get; set; } public IEnumerator GetEnumerator() => - new List { this.Reference }.GetEnumerator(); + new List { this.Reference }.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); } public class Cyclic2Exception : Exception { - public MyObjectCollection MyObjectCollection { get; set; } + public MyObjectCollection? MyObjectCollection { get; set; } } public class CyclicDictException : Exception { - public MyObjectDict MyObjectDict { get; set; } + public MyObjectDict? MyObjectDict { get; set; } } public class CyclicTaskException : Exception { - public Task Task { get; set; } + public Task? Task { get; set; } } public class MyObjectDict { - public string Foo { get; set; } + public string? Foo { get; set; } #pragma warning disable CA2227 // Collection properties should be read only - public Dictionary Reference { get; set; } + public Dictionary? Reference { get; set; } #pragma warning restore CA2227 // Collection properties should be read only } public class TypePropertyException : Exception { #pragma warning disable CA1721 // Property names should not match get methods - public int Type { get; set; } + public int? Type { get; set; } #pragma warning restore CA1721 // Property names should not match get methods } @@ -503,7 +507,7 @@ public TestException() this.PrivateProperty = "PrivateValue"; } - public static string StaticProperty { get; set; } + public static string? StaticProperty { get; set; } public string PublicProperty { get; set; } @@ -546,14 +550,14 @@ public TaskException(string message, Task task) public class RecursiveNode { - public string Name { get; set; } + public string? Name { get; set; } - public RecursiveNode Child { get; set; } + public RecursiveNode? Child { get; set; } } public class RecursiveException : Exception { - public RecursiveNode Node { get; set; } + public RecursiveNode? Node { get; set; } } [Serializable] @@ -571,7 +575,7 @@ internal class TestClass { public int ValueType { get; set; } - public string ReferenceType { get; set; } + public string? ReferenceType { get; set; } } internal class BaseClass @@ -581,7 +585,7 @@ internal class BaseClass internal class DerivedClass : BaseClass { - public new T HiddenProperty { get; set; } + public new T? HiddenProperty { get; set; } } #pragma warning disable CA1064 // Exceptions should be public diff --git a/Tests/Serilog.Exceptions.Test/Filters/CompositeExceptionPropertyFilterTest.cs b/Tests/Serilog.Exceptions.Test/Filters/CompositeExceptionPropertyFilterTest.cs index 443a1ae2..684438ce 100644 --- a/Tests/Serilog.Exceptions.Test/Filters/CompositeExceptionPropertyFilterTest.cs +++ b/Tests/Serilog.Exceptions.Test/Filters/CompositeExceptionPropertyFilterTest.cs @@ -9,7 +9,7 @@ public class CompositeExceptionPropertyFilterTest [Fact] public void CreationOfCompositeFilter_ForNullFilters_Throws() => Assert.Throws( - () => new CompositeExceptionPropertyFilter(null)); + () => new CompositeExceptionPropertyFilter(null!)); [Fact] public void CreationOfCompositeFilter_ForEmptyFilters_Throws() => @@ -21,7 +21,7 @@ public void CreationOfCompositeFilter_ForOneNullFilter_Throws() { // Act var ex = Assert.Throws( - () => new CompositeExceptionPropertyFilter(new IExceptionPropertyFilter[] { null })); + () => new CompositeExceptionPropertyFilter(new IExceptionPropertyFilter[] { null! })); // Assert Assert.Contains("index 0", ex.Message, StringComparison.Ordinal); diff --git a/Tools/ExceptionFinderTool/Program.cs b/Tools/ExceptionFinderTool/Program.cs index 03c91768..2b9ed969 100644 --- a/Tools/ExceptionFinderTool/Program.cs +++ b/Tools/ExceptionFinderTool/Program.cs @@ -17,7 +17,9 @@ public static void Main() { var stringBuilder = new StringBuilder(); - foreach (var exceptionType in GetAllAssemblies() + foreach (var exceptionType in AppDomain + .CurrentDomain + .GetAssemblies() .SelectMany(x => x.GetTypes()) .Where(x => x.GetTypeInfo().IsPublic && typeof(Exception).IsAssignableFrom(x)) .Select(x => x.FullName) @@ -30,56 +32,5 @@ public static void Main() Console.WriteLine(types); Console.Read(); } - - private static Assembly[] GetAllAssemblies() => -#if NETCOREAPP1_1 - new Assembly[] - { - Assembly.Load(new AssemblyName("System.AppContext")), - Assembly.Load(new AssemblyName("System.Collections")), - Assembly.Load(new AssemblyName("System.Collections.Concurrent")), - Assembly.Load(new AssemblyName("System.Console")), - Assembly.Load(new AssemblyName("System.Diagnostics.Debug")), - Assembly.Load(new AssemblyName("System.Diagnostics.Tools")), - Assembly.Load(new AssemblyName("System.Diagnostics.Tracing")), - Assembly.Load(new AssemblyName("System.Globalization")), - Assembly.Load(new AssemblyName("System.Globalization.Calendars")), - Assembly.Load(new AssemblyName("System.IO")), - Assembly.Load(new AssemblyName("System.IO.Compression")), - Assembly.Load(new AssemblyName("System.IO.Compression.ZipFile")), - Assembly.Load(new AssemblyName("System.IO.FileSystem")), - Assembly.Load(new AssemblyName("System.IO.FileSystem.Primitives")), - Assembly.Load(new AssemblyName("System.Linq")), - Assembly.Load(new AssemblyName("System.Linq.Expressions")), - Assembly.Load(new AssemblyName("System.Net.Http")), - Assembly.Load(new AssemblyName("System.Net.Primitives")), - Assembly.Load(new AssemblyName("System.Net.Sockets")), - Assembly.Load(new AssemblyName("System.ObjectModel")), - Assembly.Load(new AssemblyName("System.Reflection")), - Assembly.Load(new AssemblyName("System.Reflection.Extensions")), - Assembly.Load(new AssemblyName("System.Reflection.Primitives")), - Assembly.Load(new AssemblyName("System.Resources.ResourceManager")), - Assembly.Load(new AssemblyName("System.Runtime")), - Assembly.Load(new AssemblyName("System.Runtime.Extensions")), - Assembly.Load(new AssemblyName("System.Runtime.Handles")), - Assembly.Load(new AssemblyName("System.Runtime.InteropServices")), - Assembly.Load(new AssemblyName("System.Runtime.InteropServices.RuntimeInformation")), - Assembly.Load(new AssemblyName("System.Runtime.Numerics")), - Assembly.Load(new AssemblyName("System.Security.Cryptography.Algorithms")), - Assembly.Load(new AssemblyName("System.Security.Cryptography.Encoding")), - Assembly.Load(new AssemblyName("System.Security.Cryptography.Primitives")), - Assembly.Load(new AssemblyName("System.Security.Cryptography.X509Certificates")), - Assembly.Load(new AssemblyName("System.Text.Encoding")), - Assembly.Load(new AssemblyName("System.Text.Encoding.Extensions")), - Assembly.Load(new AssemblyName("System.Text.RegularExpressions")), - Assembly.Load(new AssemblyName("System.Threading")), - Assembly.Load(new AssemblyName("System.Threading.Tasks")), - Assembly.Load(new AssemblyName("System.Threading.Timer")), - Assembly.Load(new AssemblyName("System.Xml.ReaderWriter")), - Assembly.Load(new AssemblyName("System.Xml.XDocument")), - }; -#else - AppDomain.CurrentDomain.GetAssemblies(); -#endif } }