| File: parent\Shared\TaskHostBuildRequest.cs | Web Access |
| Project: MSBuild.csproj (MSBuild) |
// 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; using System.Collections.Generic; namespace Microsoft.Build.BackEnd { /// <summary> /// Packet sent from TaskHost to owning worker node to execute a BuildProjectFile* callback. /// All four BuildProjectFile/BuildProjectFilesInParallel overloads normalize to the /// IBuildEngine3 6-param canonical form carried by this packet. /// </summary> internal class TaskHostBuildRequest : INodePacket, ITaskHostCallbackPacket { private int _requestId; private string[]? _projectFileNames; private string[]? _targetNames; private Dictionary<string, string>?[]? _globalProperties; private List<string>?[]? _removeGlobalProperties; private string[]? _toolsVersions; private bool _returnTargetOutputs; public TaskHostBuildRequest() { } public TaskHostBuildRequest( string[]? projectFileNames, string[]? targetNames, Dictionary<string, string>?[]? globalProperties, List<string>?[]? removeGlobalProperties, string[]? toolsVersions, bool returnTargetOutputs) { _projectFileNames = projectFileNames; _targetNames = targetNames; _globalProperties = globalProperties; _removeGlobalProperties = removeGlobalProperties; _toolsVersions = toolsVersions; _returnTargetOutputs = returnTargetOutputs; } public NodePacketType Type => NodePacketType.TaskHostBuildRequest; public int RequestId { get => _requestId; set => _requestId = value; } /// <summary>Array of project file paths to build.</summary> public string[]? ProjectFileNames => _projectFileNames; /// <summary>Array of target names to build in each project.</summary> public string[]? TargetNames => _targetNames; /// <summary>Per-project global properties to pass to the build.</summary> public Dictionary<string, string>?[]? GlobalProperties => _globalProperties; /// <summary>Per-project global properties to remove before building.</summary> public List<string>?[]? RemoveGlobalProperties => _removeGlobalProperties; /// <summary>Per-project tools versions to use.</summary> public string[]? ToolsVersions => _toolsVersions; /// <summary>Whether to include target outputs in the response.</summary> public bool ReturnTargetOutputs => _returnTargetOutputs; /// <summary> /// Converts non-generic IDictionary[] (as used by IBuildEngine interfaces) to /// Dictionary<string, string>[] for serialization. /// </summary> internal static Dictionary<string, string>?[]? ConvertGlobalProperties(IDictionary[]? globalProperties) { if (globalProperties is null) { return null; } var result = new Dictionary<string, string>?[globalProperties.Length]; for (int i = 0; i < globalProperties.Length; i++) { if (globalProperties[i] is not null) { result[i] = new Dictionary<string, string>(globalProperties[i].Count, StringComparer.OrdinalIgnoreCase); foreach (DictionaryEntry entry in globalProperties[i]) { result[i]![(string)entry.Key] = entry.Value?.ToString() ?? string.Empty; } } } return result; } /// <summary> /// Converts IList<string>[] to List<string>[] for serialization. /// </summary> internal static List<string>?[]? ConvertRemoveGlobalProperties(IList<string>[]? removeGlobalProperties) { if (removeGlobalProperties is null) { return null; } return Array.ConvertAll(removeGlobalProperties, list => list is not null ? new List<string>(list) : null); } public void Translate(ITranslator translator) { translator.Translate(ref _requestId); TranslateNullableStringArray(translator, ref _projectFileNames); TranslateNullableStringArray(translator, ref _targetNames); translator.Translate(ref _returnTargetOutputs); TranslateNullableStringArray(translator, ref _toolsVersions); TranslateGlobalPropertiesArray(translator); TranslateRemoveGlobalPropertiesArray(translator); } /// <summary> /// Serializes a string array where individual elements may be null. /// The standard translator.Translate(ref string[]) doesn't handle null elements. /// </summary> private static void TranslateNullableStringArray(ITranslator translator, ref string[]? array) { bool hasArray = array is not null; translator.Translate(ref hasArray); if (!hasArray) { array = null; return; } int length = array?.Length ?? 0; translator.Translate(ref length); if (translator.Mode == TranslationDirection.ReadFromStream) { array = new string[length]; } for (int i = 0; i < length; i++) { string? element = array![i]; translator.Translate(ref element); array[i] = element!; } } private void TranslateGlobalPropertiesArray(ITranslator translator) { bool hasArray = _globalProperties is not null; translator.Translate(ref hasArray); if (!hasArray) { _globalProperties = null; return; } int length = _globalProperties?.Length ?? 0; translator.Translate(ref length); if (translator.Mode == TranslationDirection.ReadFromStream) { _globalProperties = new Dictionary<string, string>?[length]; } for (int i = 0; i < length; i++) { Dictionary<string, string>? dict = _globalProperties![i]; translator.TranslateDictionary(ref dict, StringComparer.OrdinalIgnoreCase); _globalProperties[i] = dict; } } private void TranslateRemoveGlobalPropertiesArray(ITranslator translator) { bool hasArray = _removeGlobalProperties is not null; translator.Translate(ref hasArray); if (!hasArray) { _removeGlobalProperties = null; return; } int length = _removeGlobalProperties?.Length ?? 0; translator.Translate(ref length); if (translator.Mode == TranslationDirection.ReadFromStream) { _removeGlobalProperties = new List<string>?[length]; } for (int i = 0; i < length; i++) { List<string>? list = _removeGlobalProperties![i]; translator.Translate(ref list); _removeGlobalProperties[i] = list; } } internal static INodePacket FactoryForDeserialization(ITranslator translator) { var packet = new TaskHostBuildRequest(); packet.Translate(translator); return packet; } } }