using QFSW.QC.Utilities; using System; using System.Collections.Generic; using System.Linq; namespace QFSW.QC { /// /// Handles formatted serialization for console returns. /// public class QuantumSerializer { private readonly IQcSerializer[] _serializers; private readonly Dictionary _serializerLookup = new Dictionary(); private readonly HashSet _unserializableLookup = new HashSet(); private readonly Func _recursiveSerializer; /// /// Creates a Quantum Serializer with a custom set of serializers. /// /// The IQcSerializers to use in this Quantum Serializer. public QuantumSerializer(IEnumerable serializers) { _recursiveSerializer = SerializeFormatted; _serializers = serializers.OrderByDescending(x => x.Priority) .ToArray(); } /// /// Creates a Quantum Serializer with the default injected serializers /// public QuantumSerializer() : this(new InjectionLoader().GetInjectedInstances()) { } /// /// Serializes the object with formatting for displaying in the console. /// /// The value to format and serialize. /// (Optional) QuantumTheme to use for formatting the results. /// The formatted serialization. public string SerializeFormatted(object value, QuantumTheme theme = null) { if (value is null) { return string.Empty; } Type type = value.GetType(); string result = string.Empty; string SerializeInternal(IQcSerializer serializer) { try { return serializer.SerializeFormatted(value, theme, _recursiveSerializer); } catch (Exception e) { throw new Exception($"Serialization of {type.GetDisplayName()} via {serializer} failed:\n{e.Message}", e); } } if (_serializerLookup.ContainsKey(type)) { result = SerializeInternal(_serializerLookup[type]); } else if (_unserializableLookup.Contains(type)) { result = value.ToString(); } else { bool converted = false; foreach (IQcSerializer serializer in _serializers) { if (serializer.CanSerialize(type)) { result = SerializeInternal(serializer); _serializerLookup[type] = serializer; converted = true; break; } } if (!converted) { result = value.ToString(); _unserializableLookup.Add(type); } } if (theme && !string.IsNullOrWhiteSpace(result)) { result = theme.ColorizeReturn(result, type); } return result; } } }