예제 #1
0
        // TODO: Remove recursion.
        public static void WriteException(
            this Utf8JsonWriter writer,
            Exception?exception,
            JsonSerializerOptions options
            )
        {
            // Validate parameters.
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // If there is no exception, write null.
            if (exception == null)
            {
                // Write null.
                writer.WriteNullValue();

                // Get out.
                return;
            }

            // Start writing the object.
            writer.WriteStartObject();

            // Write properties.
            writer.WriteString(ExceptionPropertyInfo.Message, exception.Message, options);
            writer.WriteString(ExceptionPropertyInfo.Source, exception.Source, options);
            writer.WriteNumber(ExceptionPropertyInfo.HResult, exception.HResult, options);
            writer.WriteString(ExceptionPropertyInfo.HelpLink, exception.HelpLink, options);
            writer.WriteString(ExceptionPropertyInfo.StackTrace, exception.StackTrace, options);

            // Write the property name.
            writer.WritePropertyName(ExceptionPropertyInfo.Data, options);

            // Write the data property.
            JsonSerializer.Serialize(writer, exception.Data, options);

            // Need to write the type shim.  Write the meta property
            writer.WritePropertyName("$Meta");

            // Write all the type information.
            Type type = exception.GetType();

            // Write a new object.
            writer.WriteStartObject();

            // Write the type.
            writer.WritePropertyName("Type");

            // Write a new object.
            writer.WriteStartObject();

            // Write properties.
            writer.WriteString(nameof(Type.Namespace), type.Namespace);
            writer.WriteString(nameof(Type.FullName), type.FullName);
            writer.WriteString(nameof(Type.AssemblyQualifiedName), type.AssemblyQualifiedName);
            writer.WriteString(nameof(Type.Name), type.Name);

            // Close the type then the meta object.
            writer.WriteEndObject();
            writer.WriteEndObject();

            // Are there any properties which are assignable
            // to exception or IEnumerable<Exception>?
            // If so, write those.  Cycle through the properties.
            foreach (PropertyInfo propertyInfo in type.GetPropertiesWithPublicInstanceGetters())
            {
                // Is it assignable to exception?
                if (Constant.ExceptionTypeInfo.IsAssignableFrom(propertyInfo.PropertyType))
                {
                    // Write the property name.
                    writer.WritePropertyName(propertyInfo, options);

                    // Write the object.
                    writer.WriteException((Exception?)propertyInfo.GetValue(exception), options);
                }
                // If this is assignable to an IEnumerable<Exception> then
                // get that.
                else if (Constant.EnumerableExceptionTypeInfo.IsAssignableFrom(propertyInfo.PropertyType))
                {
                    // Get the value.
                    var exceptions = (IEnumerable <Exception>?)propertyInfo.GetValue(exception);

                    // Write the property name.
                    writer.WritePropertyName(propertyInfo, options);

                    // Write the exception array.
                    writer.WriteExceptionArray(exceptions, options);

                    // Continue.
                    continue;
                }
            }

            // Write the end of the object.
            writer.WriteEndObject();
        }