Пример #1
0
        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 }));
        }