/// <summary> /// Populate the lists of evaluated and unevaluated metadata with all metadata that have true conditions. /// </summary> /// <remarks> /// FUTURE: Currently this isn't done when the item is constructed; so for example HasMetadata will always return /// false until EvaluatedAllItemMetadata is explicitly called. The reason for this is that Metadata are /// not first class objects, they are merely string pairs produced by running over the child XML with a particular expander. /// When Metadata are first class objects this method can be changed to merely evaluate them, /// just as BuildItemGroup.Evaluate does for BuildItem, then methods like HasMetadata behave more sanely. Of course this /// could be a breaking change. /// </remarks> internal void EvaluateAllItemMetadata ( Expander expander, ParserOptions parserOptions, EngineLoggingServices loggingServices, BuildEventContext buildEventContext ) { ErrorUtilities.VerifyThrow(expander != null, "Null expander passed in."); // Cache all custom attributes on the item. For a persisted item, this will walk the item's child nodes, and // cache the custom attributes using a "last one wins" policy. For a virtual item, this method does nothing. // We only evaluate metadata by reading XML if (IsBackedByXml) { ErrorUtilities.VerifyThrow((this.evaluatedCustomMetadata != null) && (this.unevaluatedCustomMetadata != null), "Item is not initialized properly."); // We're evaluating from scratch, so clear out any old cached attributes. this.evaluatedCustomMetadata.Clear(); this.unevaluatedCustomMetadata.Clear(); // Let the expander know about our own item type, so it can // expand unqualified metadata expressions SpecificItemDefinitionLibrary specificItemDefinitionLibrary = new SpecificItemDefinitionLibrary(name, itemDefinitionLibrary); expander = new Expander(expander, specificItemDefinitionLibrary); List<XmlElement> metadataElements = xml.GetChildren(); // look at all the item's child nodes foreach (XmlElement metadataElement in metadataElements) { // confirm that the child node is not conditionally disabled bool condition = true; XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(metadataElement, true /*no other attributes allowed*/); if (conditionAttribute != null) { condition = Utilities.EvaluateCondition(conditionAttribute.Value, conditionAttribute, expander, null, parserOptions, loggingServices, buildEventContext); } if (condition) { // cache its value, both the evaluated and unevaluated. string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(metadataElement); unevaluatedCustomMetadata[metadataElement.Name] = unevaluatedMetadataValue; string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, metadataElement); evaluatedCustomMetadata[metadataElement.Name] = evaluatedMetadataValue; // Add this metadata to the running table we're using, so that one piece of metadata can refer to another one above expander.SetMetadataInMetadataTable(name, metadataElement.Name, evaluatedMetadataValue); } } } }
internal Expander(Expander expander, SpecificItemDefinitionLibrary itemDefinitionLibrary) : this(expander.lookup, null , expander.options) { if (implicitMetadataItemType == null) { this.itemMetadata = expander.itemMetadata; } this.specificItemDefinitionLibrary = itemDefinitionLibrary; }