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; while (runtimeType.GetCustomAttribute <SerializableAttribute>() is null || (ctor = FindDeserializingConstructor(runtimeType)) is null) { string errorMessage = $"{runtimeType.FullName} does not declare a deserializing constructor with signature ({string.Join(", ", DeserializingConstructorParameterTypes.Select(t => t.FullName))})."; traceSource?.TraceEvent(TraceEventType.Warning, (int)JsonRpc.TraceEvents.ExceptionNotDeserializable, errorMessage); runtimeType = runtimeType.BaseType; if (runtimeType is null) { throw new NotSupportedException(errorMessage); } } return((T)ctor.Invoke(new object?[] { info, Context })); }