diff --git a/src/Serilog/Parameters/PropertyValueConverter.cs b/src/Serilog/Parameters/PropertyValueConverter.cs index c805ead9f..beeabcac0 100644 --- a/src/Serilog/Parameters/PropertyValueConverter.cs +++ b/src/Serilog/Parameters/PropertyValueConverter.cs @@ -61,13 +61,13 @@ public PropertyValueConverter(int maximumDestructuringDepth, IEnumerable a new NullableScalarConversionPolicy(), new EnumScalarConversionPolicy(), new ByteArrayScalarConversionPolicy(), - new ReflectionTypesScalarConversionPolicy() }; _destructuringPolicies = additionalDestructuringPolicies - .Concat(new [] + .Concat(new IDestructuringPolicy [] { - new DelegateDestructuringPolicy() + new DelegateDestructuringPolicy(), + new ReflectionTypesScalarDestructuringPolicy() }) .ToArray(); } diff --git a/src/Serilog/Policies/ReflectionTypesScalarConversionPolicy.cs b/src/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs similarity index 80% rename from src/Serilog/Policies/ReflectionTypesScalarConversionPolicy.cs rename to src/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs index 0d8996bd2..5b2d944c8 100644 --- a/src/Serilog/Policies/ReflectionTypesScalarConversionPolicy.cs +++ b/src/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs @@ -1,4 +1,4 @@ -// Copyright 2013-2015 Serilog Contributors +// Copyright 2013-2016 Serilog Contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ namespace Serilog.Policies { - class ReflectionTypesScalarConversionPolicy : IScalarConversionPolicy + class ReflectionTypesScalarDestructuringPolicy : IDestructuringPolicy { - public bool TryConvertToScalar(object value, ILogEventPropertyValueFactory propertyValueFactory, out ScalarValue result) + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { // These types and their subclasses are property-laden and deep; // most sinks will convert them to strings. diff --git a/test/Serilog.Tests/LoggerConfigurationTests.cs b/test/Serilog.Tests/LoggerConfigurationTests.cs index 7c5c22e14..92e148754 100644 --- a/test/Serilog.Tests/LoggerConfigurationTests.cs +++ b/test/Serilog.Tests/LoggerConfigurationTests.cs @@ -2,6 +2,7 @@ using System.IO; using System.Collections.Generic; using System.Linq; +using System.Reflection; using Xunit; using Serilog.Core; using Serilog.Core.Filters; @@ -109,6 +110,76 @@ public void SpecifyingThatATypeIsScalarCausesItToBeLoggedAsScalarEvenWhenDestruc Assert.IsType(prop); } + [Fact] + public void DestructuringSystemTypeGivesScalarByDefault() + { + var events = new List(); + var sink = new DelegatingSink(events.Add); + + var logger = new LoggerConfiguration() + .WriteTo.Sink(sink) + .CreateLogger(); + + var thisType = this.GetType(); + logger.Information("{@thisType}", thisType); + + var ev = events.Single(); + var prop = ev.Properties["thisType"]; + var sv = Assert.IsAssignableFrom(prop); + Assert.Equal(thisType, sv.LiteralValue()); + } + + class ProjectedDestructuringPolicy : IDestructuringPolicy + { + readonly Func _canApply; + readonly Func _projection; + + public ProjectedDestructuringPolicy(Func canApply, Func projection) + { + if (canApply == null) throw new ArgumentNullException(nameof(canApply)); + if (projection == null) throw new ArgumentNullException(nameof(projection)); + _canApply = canApply; + _projection = projection; + } + + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + + if (!_canApply(value.GetType())) + { + result = null; + return false; + } + + var projected = _projection(value); + result = propertyValueFactory.CreatePropertyValue(projected, true); + return true; + } + } + + [Fact] + public void DestructuringIsPossibleForSystemTypeDerivedProperties() + { + var events = new List(); + var sink = new DelegatingSink(events.Add); + + var logger = new LoggerConfiguration() + .Destructure.With(new ProjectedDestructuringPolicy( + canApply: t => typeof(Type).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()), + projection: o => ((Type)o).AssemblyQualifiedName)) + .WriteTo.Sink(sink) + .CreateLogger(); + + var thisType = this.GetType(); + logger.Information("{@thisType}", thisType); + + var ev = events.Single(); + var prop = ev.Properties["thisType"]; + var sv = Assert.IsAssignableFrom(prop); + Assert.Equal(thisType.AssemblyQualifiedName, sv.LiteralValue()); + } + [Fact] public void TransformationsAreAppliedToEventProperties() { diff --git a/test/Serilog.Tests/Parameters/PropertyValueConverterTests.cs b/test/Serilog.Tests/Parameters/PropertyValueConverterTests.cs index 4fca562ad..f935855b4 100644 --- a/test/Serilog.Tests/Parameters/PropertyValueConverterTests.cs +++ b/test/Serilog.Tests/Parameters/PropertyValueConverterTests.cs @@ -167,7 +167,15 @@ public void FailsGracefullyWhenGettersThrow() public void SurvivesDestructuringASystemType() { var pv = _converter.CreatePropertyValue(typeof(string), Destructuring.Destructure); - Assert.Equal(typeof(string), pv.LiteralValue()); + Assert.Equal(typeof(string), pv.LiteralValue()); + } + + [Fact] + public void SurvivesDestructuringMethodBase() + { + var theMethod = System.Reflection.MethodBase.GetCurrentMethod(); + var pv = _converter.CreatePropertyValue(theMethod, Destructuring.Destructure); + Assert.Equal(theMethod, pv.LiteralValue()); } public class BaseWithProps