Skip to content

Commit

Permalink
Taking a stab at issue serilog#30. The IDestructuringPolicies are now…
Browse files Browse the repository at this point in the history
… run before IEnumerable cast -- allowing an opportunity for policies to support IEnumerable values. Added IsValueTypeDictionary function to simplify the look of the dictionary conversion code.
  • Loading branch information
Jaben committed Feb 3, 2015
1 parent 9532db2 commit 0b3cee8
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 39 deletions.
46 changes: 26 additions & 20 deletions src/Serilog/Parameters/PropertyValueConverter-net40.cs
Expand Up @@ -105,14 +105,24 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur

var valueType = value.GetType();
var limiter = new DepthLimiter(depth, _maximumDestructuringDepth, this);

foreach (var scalarConversionPolicy in _scalarConversionPolicies)
{
ScalarValue converted;
if (scalarConversionPolicy.TryConvertToScalar(value, limiter, out converted))
return converted;
}

if (destructuring == Destructuring.Destructure)
{
foreach (var destructuringPolicy in _destructuringPolicies)
{
LogEventPropertyValue result;
if (destructuringPolicy.TryDestructure(value, limiter, out result))
return result;
}
}

var enumerable = value as IEnumerable;
if (enumerable != null)
{
Expand All @@ -124,32 +134,22 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
// Only actual dictionaries are supported, as arbitrary types
// can implement multiple IDictionary interfaces and thus introduce
// multiple different interpretations.
if (valueType.IsGenericType &&
valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
IsValidDictionaryKeyType(valueType.GetGenericArguments()[0]))
if (IsValueTypeDictionary(valueType))
{
return new DictionaryValue(enumerable.Cast<dynamic>()
.Select(kvp => new KeyValuePair<ScalarValue, LogEventPropertyValue>(
(ScalarValue)limiter.CreatePropertyValue(kvp.Key, destructuring),
limiter.CreatePropertyValue(kvp.Value, destructuring)))
(ScalarValue)limiter.CreatePropertyValue(kvp.Key, destructuring),
limiter.CreatePropertyValue(kvp.Value, destructuring)))
.Where(kvp => kvp.Key.Value != null));
}

return new SequenceValue(
enumerable.Cast<object>().Select(o => limiter.CreatePropertyValue(o, destructuring)));
return
new SequenceValue(
enumerable.Cast<object>().Select(o => limiter.CreatePropertyValue(o, destructuring)));
}

// Unknown types


if (destructuring == Destructuring.Destructure)
{
foreach (var destructuringPolicy in _destructuringPolicies)
{
LogEventPropertyValue result;
if (destructuringPolicy.TryDestructure(value, limiter, out result))
return result;
}

var typeTag = value.GetType().Name;
if (typeTag.Length <= 0 || !char.IsLetter(typeTag[0]))
typeTag = null;
Expand All @@ -160,10 +160,16 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
return new ScalarValue(value.ToString());
}

bool IsValueTypeDictionary(Type valueType)
{
return valueType.IsGenericType &&
valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
IsValidDictionaryKeyType(valueType.GetGenericArguments()[0]);
}

bool IsValidDictionaryKeyType(Type valueType)
{
return BuiltInScalarTypes.Contains(valueType) ||
valueType.IsEnum;
return BuiltInScalarTypes.Contains(valueType) || valueType.IsEnum;
}

static IEnumerable<LogEventProperty> GetProperties(object value, ILogEventPropertyValueFactory recursive)
Expand Down
45 changes: 26 additions & 19 deletions src/Serilog/Parameters/PropertyValueConverter.cs
Expand Up @@ -106,14 +106,24 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur

var valueType = value.GetType();
var limiter = new DepthLimiter(depth, _maximumDestructuringDepth, this);

foreach (var scalarConversionPolicy in _scalarConversionPolicies)
{
ScalarValue converted;
if (scalarConversionPolicy.TryConvertToScalar(value, limiter, out converted))
return converted;
}

if (destructuring == Destructuring.Destructure)
{
foreach (var destructuringPolicy in _destructuringPolicies)
{
LogEventPropertyValue result;
if (destructuringPolicy.TryDestructure(value, limiter, out result))
return result;
}
}

var enumerable = value as IEnumerable;
if (enumerable != null)
{
Expand All @@ -125,32 +135,22 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
// Only actual dictionaries are supported, as arbitrary types
// can implement multiple IDictionary interfaces and thus introduce
// multiple different interpretations.
if (valueType.IsConstructedGenericType &&
valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
IsValidDictionaryKeyType(valueType.GenericTypeArguments[0]))
if (IsValueTypeDictionary(valueType))
{
return new DictionaryValue(enumerable.Cast<dynamic>()
.Select(kvp => new KeyValuePair<ScalarValue, LogEventPropertyValue>(
(ScalarValue)limiter.CreatePropertyValue(kvp.Key, destructuring),
limiter.CreatePropertyValue(kvp.Value, destructuring)))
.Where(kvp => kvp.Key.Value != null)); // Limiting may kick in
(ScalarValue)limiter.CreatePropertyValue(kvp.Key, destructuring),
limiter.CreatePropertyValue(kvp.Value, destructuring)))
.Where(kvp => kvp.Key.Value != null));
}

return new SequenceValue(
enumerable.Cast<object>().Select(o => limiter.CreatePropertyValue(o, destructuring)));
return
new SequenceValue(
enumerable.Cast<object>().Select(o => limiter.CreatePropertyValue(o, destructuring)));
}

// Unknown types


if (destructuring == Destructuring.Destructure)
{
foreach (var destructuringPolicy in _destructuringPolicies)
{
LogEventPropertyValue result;
if (destructuringPolicy.TryDestructure(value, limiter, out result))
return result;
}

var typeTag = value.GetType().Name;
if (typeTag.Length <= 0 || !char.IsLetter(typeTag[0]))
typeTag = null;
Expand All @@ -161,6 +161,13 @@ LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructur
return new ScalarValue(value.ToString());
}

bool IsValueTypeDictionary(Type valueType)
{
return valueType.IsGenericType &&
valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>) &&
IsValidDictionaryKeyType(valueType.GetGenericArguments()[0]);
}

bool IsValidDictionaryKeyType(Type valueType)
{
return BuiltInScalarTypes.Contains(valueType) ||
Expand Down

0 comments on commit 0b3cee8

Please sign in to comment.