| File: BuildException\BuildExceptionSerializationHelper.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.Threading; namespace Microsoft.Build.Framework.BuildException { internal static class BuildExceptionSerializationHelper { public class TypeConstructionTuple { public TypeConstructionTuple(Type type, Func<string, Exception?, BuildExceptionBase> factory) { Type = type; Factory = factory; } public Type Type { get; } public Func<string, Exception?, BuildExceptionBase> Factory { get; } } private static Dictionary<string, Func<string, Exception?, BuildExceptionBase>>? s_exceptionFactories; private static readonly Func<string, Exception?, BuildExceptionBase> s_defaultFactory = (message, innerException) => new GenericBuildTransferredException(message, innerException); internal static bool IsSupportedExceptionType(Type type) { return type.IsClass && !type.IsAbstract && type.IsSubclassOf(typeof(Exception)) && type.IsSubclassOf(typeof(BuildExceptionBase)); } internal static void InitializeSerializationContract(params TypeConstructionTuple[] exceptionsAllowlist) { InitializeSerializationContract((IEnumerable<TypeConstructionTuple>)exceptionsAllowlist); } internal static void InitializeSerializationContract(IEnumerable<TypeConstructionTuple> exceptionsAllowlist) { if (s_exceptionFactories != null) { return; } var exceptionFactories = new Dictionary<string, Func<string, Exception?, BuildExceptionBase>>(); foreach (TypeConstructionTuple typeConstructionTuple in exceptionsAllowlist) { Type exceptionType = typeConstructionTuple.Type; Func<string, Exception?, BuildExceptionBase> exceptionFactory = typeConstructionTuple.Factory; Assumed.True(IsSupportedExceptionType(exceptionType), $"Type {exceptionType.FullName} is not recognized as a build exception type."); string key = GetExceptionSerializationKey(exceptionType); exceptionFactories[key] = exceptionFactory; } if (Interlocked.Exchange(ref s_exceptionFactories, exceptionFactories) != null) { InternalError.Throw("Serialization contract was already initialized."); } } internal static string GetExceptionSerializationKey(Type exceptionType) { return exceptionType.FullName ?? exceptionType.ToString(); } internal static Func<string, Exception?, BuildExceptionBase> CreateExceptionFactory(string serializationType) { Assumed.NotNull(s_exceptionFactories, "Serialization contract was not initialized."); return s_exceptionFactories.TryGetValue(serializationType, out Func<string, Exception?, BuildExceptionBase>? factory) ? factory ?? s_defaultFactory : s_defaultFactory; } } }