// 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; } } }