internal static T Deserialize()

in src/StreamJsonRpc/Reflection/ExceptionSerializationHelpers.cs [30:88]


        internal static T Deserialize<T>(JsonRpc jsonRpc, SerializationInfo info, TraceSource? traceSource)
            where T : Exception
        {
            if (!TryGetValue(info, "ClassName", out string? runtimeTypeName) || runtimeTypeName is null)
            {
                throw new NotSupportedException("ClassName was not found in the serialized data.");
            }

            TryGetValue(info, AssemblyNameKeyName, out string? runtimeAssemblyName);
            Type? runtimeType = jsonRpc.LoadType(runtimeTypeName, runtimeAssemblyName);
            if (runtimeType is null)
            {
                if (traceSource?.Switch.ShouldTrace(TraceEventType.Warning) ?? false)
                {
                    traceSource.TraceEvent(TraceEventType.Warning, (int)JsonRpc.TraceEvents.ExceptionTypeNotFound, "{0} type could not be loaded. Falling back to System.Exception.", runtimeTypeName);
                }

                // fallback to deserializing the base Exception type.
                runtimeType = typeof(Exception);
            }

            // Sanity/security check: ensure the runtime type derives from the expected type.
            if (!typeof(T).IsAssignableFrom(runtimeType))
            {
                throw new NotSupportedException($"{runtimeTypeName} does not derive from {typeof(T).FullName}.");
            }

            // Find the nearest exception type that implements the deserializing constructor and is deserializable.
            ConstructorInfo? ctor = null;
            Type? originalRuntimeType = runtimeType;
            while (runtimeType is object)
            {
                string? errorMessage =
                    runtimeType.GetCustomAttribute<SerializableAttribute>() is null ? $"{runtimeType.FullName} is not annotated with a {nameof(SerializableAttribute)}." :
                    !jsonRpc.ExceptionOptions.CanDeserialize(runtimeType) ? $"{runtimeType.FullName} is not an allowed type to deserialize." :
                    (ctor = FindDeserializingConstructor(runtimeType)) is null ? $"{runtimeType.FullName} does not declare a deserializing constructor with signature ({string.Join(", ", DeserializingConstructorParameterTypes.Select(t => t.FullName))})." :
                    null;
                if (errorMessage is null)
                {
                    break;
                }

                if (runtimeType.BaseType is Type baseType)
                {
                    errorMessage += $" {baseType.FullName} will be deserialized instead, if possible.";
                }

                traceSource?.TraceEvent(TraceEventType.Warning, (int)JsonRpc.TraceEvents.ExceptionNotDeserializable, errorMessage);

                runtimeType = runtimeType.BaseType;
            }

            if (ctor is null)
            {
                throw new NotSupportedException($"{originalRuntimeType.FullName} is not a supported exception type to deserialize and no adequate substitute could be found.");
            }

            return (T)ctor.Invoke(new object?[] { info, Context });
        }