From 35606d2cd04a7b1bec1d669f9619501dff2bf9dc Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 22 Apr 2021 17:38:36 -0700 Subject: Simplify heat by creating a single executable --- src/heat/Serialize/CodeDomReader.cs | 162 ++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 src/heat/Serialize/CodeDomReader.cs (limited to 'src/heat/Serialize/CodeDomReader.cs') diff --git a/src/heat/Serialize/CodeDomReader.cs b/src/heat/Serialize/CodeDomReader.cs new file mode 100644 index 00000000..0741bf68 --- /dev/null +++ b/src/heat/Serialize/CodeDomReader.cs @@ -0,0 +1,162 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Harvesters.Serialize +{ + using System; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.Reflection; + using System.Xml; + using WixToolset.Harvesters.Extensibility.Serialize; + + /// + /// Class used for reading XML files in to the CodeDom. + /// + public class CodeDomReader + { + private Assembly[] assemblies; + + /// + /// Creates a new CodeDomReader, using the current assembly. + /// + public CodeDomReader() + { + this.assemblies = new Assembly[] { Assembly.GetExecutingAssembly() }; + } + + /// + /// Creates a new CodeDomReader, and takes in a list of assemblies in which to + /// look for elements. + /// + /// Assemblies in which to look for types that correspond + /// to elements. + public CodeDomReader(Assembly[] assemblies) + { + this.assemblies = assemblies; + } + + /// + /// Loads an XML file into a strongly-typed code dom. + /// + /// File to load into the code dom. + /// The strongly-typed object at the root of the tree. + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")] + public ISchemaElement Load(string filePath) + { + XmlDocument document = new XmlDocument(); + document.Load(filePath); + ISchemaElement schemaElement = null; + + foreach (XmlNode node in document.ChildNodes) + { + XmlElement element = node as XmlElement; + if (element != null) + { + if (schemaElement != null) + { + throw new InvalidOperationException(WixHarvesterStrings.EXP_MultipleRootElementsFoundInFile); + } + + schemaElement = this.CreateObjectFromElement(element); + this.ParseObjectFromElement(schemaElement, element); + } + } + return schemaElement; + } + + /// + /// Sets an attribute on an ISchemaElement. + /// + /// Schema element to set attribute on. + /// Name of the attribute to set. + /// Value to set on the attribute. + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")] + private static void SetAttributeOnObject(ISchemaElement schemaElement, string name, string value) + { + ISetAttributes setAttributes = schemaElement as ISetAttributes; + if (setAttributes == null) + { + throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixHarvesterStrings.EXP_ISchemaElementDoesnotImplementISetAttribute, schemaElement.GetType().FullName)); + } + else + { + setAttributes.SetAttribute(name, value); + } + } + + /// + /// Parses an ISchemaElement from the XmlElement. + /// + /// ISchemaElement to fill in. + /// XmlElement to parse from. + [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")] + private void ParseObjectFromElement(ISchemaElement schemaElement, XmlElement element) + { + foreach (XmlAttribute attribute in element.Attributes) + { + SetAttributeOnObject(schemaElement, attribute.LocalName, attribute.Value); + } + + foreach (XmlNode node in element.ChildNodes) + { + XmlElement childElement = node as XmlElement; + if (childElement != null) + { + ISchemaElement childSchemaElement = null; + ICreateChildren createChildren = schemaElement as ICreateChildren; + if (createChildren == null) + { + throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixHarvesterStrings.EXP_ISchemaElementDoesnotImplementICreateChildren, element.LocalName)); + } + else + { + childSchemaElement = createChildren.CreateChild(childElement.LocalName); + } + + if (childSchemaElement == null) + { + childSchemaElement = this.CreateObjectFromElement(childElement); + if (childSchemaElement == null) + { + throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixHarvesterStrings.EXP_XmlElementDoesnotHaveISchemaElement, childElement.LocalName)); + } + } + + this.ParseObjectFromElement(childSchemaElement, childElement); + IParentElement parentElement = (IParentElement)schemaElement; + parentElement.AddChild(childSchemaElement); + } + else + { + XmlText childText = node as XmlText; + if (childText != null) + { + SetAttributeOnObject(schemaElement, "Content", childText.Value); + } + } + } + } + + /// + /// Creates an object from an XML element by digging through the assembly list. + /// + /// XML Element to create an ISchemaElement from. + /// A constructed ISchemaElement. + private ISchemaElement CreateObjectFromElement(XmlElement element) + { + ISchemaElement schemaElement = null; + foreach (Assembly assembly in this.assemblies) + { + foreach (Type type in assembly.GetTypes()) + { + if (type.FullName.EndsWith(element.LocalName, StringComparison.Ordinal) + && typeof(ISchemaElement).IsAssignableFrom(type)) + { + schemaElement = (ISchemaElement)Activator.CreateInstance(type); + } + } + } + return schemaElement; + } + } +} -- cgit v1.2.3-55-g6feb