private static void AppendScope(IDictionary <string, object> dictionary, object scope) { switch (scope) { case null: return; case IReadOnlyList <KeyValuePair <string, object> > formattedLogValues: { if (formattedLogValues.Count > 0) { foreach (var value in formattedLogValues) { if (value.Value is MethodInfo) { continue; } dictionary[value.Key] = value.Value; } } break; } default: { var appendToDictionaryMethod = ExpressionCache.GetOrCreateAppendToDictionaryMethod(scope.GetType()); appendToDictionaryMethod(dictionary, scope); break; } } }
private static void AppendScope(IDictionary <string, object> dictionary, object scope) { if (scope == null) { return; } // The scope can be defined using BeginScope or LogXXX methods. // - logger.BeginScope(new { Author = "meziantou" }) // - logger.LogInformation("Hello {Author}", "meziaantou") // Using LogXXX, an object of type FormattedLogValues is created. This type is internal but it implements IReadOnlyList, so we can use it. // https://github.com/aspnet/Extensions/blob/cc9a033c6a8a4470984a4cc8395e42b887c07c2e/src/Logging/Logging.Abstractions/src/FormattedLogValues.cs if (scope is IReadOnlyList <KeyValuePair <string, object> > formattedLogValues) { if (formattedLogValues.Count > 0) { foreach (var value in formattedLogValues) { // MethodInfo is set by ASP.NET Core when reaching a controller. This type cannot be serialized using JSON.NET, but I don't need it. if (value.Value is MethodInfo) { continue; } dictionary[value.Key] = value.Value; } } } else { // The idea is to get the value of all properties of the object and add them to the dictionary. // dictionary["Prop1"] = scope.Prop1; // dictionary["Prop2"] = scope.Prop2; // ... // We always log the same objects, so we can create a cache of compiled expressions to fill the dictionary. // Using reflection each time would slow down the logger. var appendToDictionaryMethod = ExpressionCache.GetOrCreateAppendToDictionaryMethod(scope.GetType()); appendToDictionaryMethod(dictionary, scope); } }