| File: BuildException\BuildExceptionBase.cs | Web Access |
| Project: src\msbuild\src\Framework\Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.Serialization; using Microsoft.Build.BackEnd; namespace Microsoft.Build.Framework.BuildException; public abstract class BuildExceptionBase : Exception { private string? _remoteTypeName; private string? _remoteStackTrace; private protected BuildExceptionBase() : base() { } private protected BuildExceptionBase(string? message) : base(message) { } private protected BuildExceptionBase( string? message, Exception? inner) : base(message, inner) { } // This is needed to allow opting back in to BinaryFormatter serialization #if NET8_0_OR_GREATER [Obsolete(DiagnosticId = "SYSLIB0051")] #endif private protected BuildExceptionBase(SerializationInfo info, StreamingContext context) : base(info, context) { } public override string? StackTrace => string.IsNullOrEmpty(_remoteStackTrace) ? base.StackTrace : _remoteStackTrace; public override string ToString() => string.IsNullOrEmpty(_remoteTypeName) ? base.ToString() : $"{_remoteTypeName}->{base.ToString()}"; /// <summary> /// Override this method to recover subtype-specific state from the remote exception. /// </summary> protected virtual void InitializeCustomState(IDictionary<string, string?>? customKeyedSerializedData) { } /// <summary> /// Override this method to provide subtype-specific state to be serialized. /// </summary> /// <returns></returns> protected virtual IDictionary<string, string?>? FlushCustomState() { return null; } private void InitializeFromRemoteState(BuildExceptionRemoteState remoteState) { _remoteTypeName = remoteState.RemoteTypeName; _remoteStackTrace = remoteState.RemoteStackTrace; base.Source = remoteState.Source; base.HelpLink = remoteState.HelpLink; base.HResult = remoteState.HResult; if (remoteState.Source != null) { InitializeCustomState(remoteState.CustomKeyedSerializedData); } } internal static void WriteExceptionToTranslator(ITranslator translator, Exception exception) { BinaryWriter writer = translator.Writer; writer.Write(exception.InnerException != null); if (exception.InnerException != null) { WriteExceptionToTranslator(translator, exception.InnerException); } string serializationType = BuildExceptionSerializationHelper.GetExceptionSerializationKey(exception.GetType()); writer.Write(serializationType); writer.Write(exception.Message); writer.WriteOptionalString(exception.StackTrace); writer.WriteOptionalString(exception.Source); writer.WriteOptionalString(exception.HelpLink); // HResult is completely protected up till net4.5 #if NET || NET45_OR_GREATER int? hresult = exception.HResult; #else int? hresult = null; #endif writer.WriteOptionalInt32(hresult); IDictionary<string, string?>? customKeyedSerializedData = (exception as BuildExceptionBase)?.FlushCustomState(); if (customKeyedSerializedData == null) { writer.Write((byte)0); } else { writer.Write((byte)1); writer.Write(customKeyedSerializedData.Count); foreach (var pair in customKeyedSerializedData) { writer.Write(pair.Key); writer.WriteOptionalString(pair.Value); } } Debug.Assert((exception.Data?.Count ?? 0) == 0, "Exception Data is not supported in BuildTransferredException"); } internal static Exception ReadExceptionFromTranslator(ITranslator translator) { BinaryReader reader = translator.Reader; Exception? innerException = null; if (reader.ReadBoolean()) { innerException = ReadExceptionFromTranslator(translator); } string serializationType = reader.ReadString(); string message = reader.ReadString(); string? deserializedStackTrace = reader.ReadOptionalString(); string? source = reader.ReadOptionalString(); string? helpLink = reader.ReadOptionalString(); int hResult = reader.ReadOptionalInt32() ?? 0; IDictionary<string, string?>? customKeyedSerializedData = null; if (reader.ReadByte() == 1) { int count = reader.ReadInt32(); customKeyedSerializedData = new Dictionary<string, string?>(count, StringComparer.CurrentCulture); for (int i = 0; i < count; i++) { customKeyedSerializedData[reader.ReadString()] = reader.ReadOptionalString(); } } BuildExceptionBase exception = BuildExceptionSerializationHelper.CreateExceptionFactory(serializationType)(message, innerException); exception.InitializeFromRemoteState( new BuildExceptionRemoteState( serializationType, deserializedStackTrace, source, helpLink, hResult, customKeyedSerializedData)); return exception; } }