/// <summary>
        /// Parses a contentsOfVariableName specification in composition XML in its short-hand form.
        /// </summary>
        public static object ParseWindowsRegistry(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string keyPath   = null;
            string valueName = null;

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "windowsRegistryKeyPath":
                    keyPath = attribute.Value;
                    break;

                case "windowsRegistryValueName":
                    valueName = attribute.Value;
                    break;

                default:
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for windowsRegistry value elements.", attribute.Name));
                    return(null);
                }
            }

            if (keyPath == null)
            {
                context.ReportError("Attribute 'windowsRegistryKeyPath' is required.");
                return(null);
            }

            return(ParseWindowsRegistry(keyPath, valueName, context));
        }
        /// <summary>
        /// Used for parsing short-hand form of specifying an object in the parent element
        /// </summary>
        public static object ParseObject(XmlAttribute[] attributes, XmlElement[] childElements, XmlProcessingContext context)
        {
            string typeName        = null;
            var    initializePlugs = false;

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "objectType":
                    typeName = attribute.Value;
                    break;

                case "objectInitializePlugs":
                    initializePlugs = Boolean.Parse(attribute.Value);
                    break;

                default:
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for object value elements.", attribute.Name));
                    return(null);
                }
            }

            if (typeName == null)
            {
                context.ReportError("Attribute 'objectType' is required.");
                return(null);
            }

            return(ParseObject(typeName, initializePlugs, childElements, context));
        }
        private static void ParseDictionaryItem(IDictionary result, XmlElement childElement,
                                                XmlProcessingContext xmlProcessingContext)
        {
            if (childElement.GetElementsByTagName("Key").Count != 1)
            {
                xmlProcessingContext.ReportError(
                    "Each 'Item' in a 'Dictionary' should contain exactly one 'Key' element as a nested tag.");
                return;
            }

            if (childElement.GetElementsByTagName("Value").Count != 1)
            {
                xmlProcessingContext.ReportError(
                    "Each 'Item' in a 'Dictionary' should contain exactly one 'Value' element as a nested tag.");
                return;
            }

            xmlProcessingContext.EnterRunningLocation("Key");
            var keyValue =
                XmlValueParser.ParseValue((XmlElement)childElement.GetElementsByTagName("Key")[0], xmlProcessingContext, null);

            xmlProcessingContext.LeaveRunningLocation();

            xmlProcessingContext.EnterRunningLocation("Value");
            var valueValue =
                XmlValueParser.ParseValue((XmlElement)childElement.GetElementsByTagName("Value")[0], xmlProcessingContext, null);

            xmlProcessingContext.LeaveRunningLocation();

            result.Add(keyValue, valueValue);
        }
        /// <summary>
        /// Parses a contentsOfVariableName specification in composition XML in its short-hand form.
        /// </summary>
        public static object ParseContentsOfVariable(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string variableName = null;

            foreach (var attribute in attributes)
            {
                if (attribute.Name == "contentsOfVariableName")
                {
                    variableName = attribute.Value;
                }
                else
                {
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for contentsOfVariable value elements.", attribute.Name));
                    return(null);
                }
            }

            if (variableName == null)
            {
                context.ReportError("Attribute 'contentsOfVariableName' is required.");
                return(null);
            }

            return(ParseContentsOfVariable(variableName, context));
        }
        /// <summary>
        /// Parses a ContentsOfVariable element in the composition XML.
        /// </summary>
        public static object ParseWindowsRegistry(XmlElement element, XmlProcessingContext context)
        {
            if (element.ChildNodes.Count > 0)
            {
                context.ReportError("'WindowsRegistry' elements should not contain any child elements.");
                return(null);
            }

            string keyPath   = null;
            string valueName = null;

            if (element.Attributes["keyPath"] != null)
            {
                keyPath = element.Attributes["keyPath"].Value;
            }

            if (element.Attributes["valueName"] != null)
            {
                valueName = element.Attributes["valueName"].Value;
            }

            if (keyPath == null)
            {
                context.ReportError("'WindowsRegistry' elements require a 'keyPath' attribute.");
                return(null);
            }

            return(ParseWindowsRegistry(keyPath, valueName, context));
        }
        private static void ParseObjectProperty(object result, XmlElement childElement,
                                                XmlProcessingContext xmlProcessingContext)
        {
            if (childElement.Attributes["name"] == null)
            {
                xmlProcessingContext.ReportError("'Property' element in the composition XML should have a 'name' attribute.");
                return;
            }

            var propertyName = childElement.Attributes["name"].Value;

            xmlProcessingContext.EnterRunningLocation(string.Format("Property({0})", propertyName));

            var propertyInfo = result.GetType().GetProperty(propertyName);

            if (propertyInfo == null)
            {
                xmlProcessingContext.ReportError(
                    string.Format("Object type '{0}' does not contain a property definition named '{1}", result.GetType().FullName,
                                  propertyName));
                xmlProcessingContext.LeaveRunningLocation();
                return;
            }

            var propertyValue =
                XmlValueParser.ParseValue(childElement, xmlProcessingContext, ObjectPropertyExcludedAttributes);

            propertyInfo.SetValue(result, propertyValue, null);

            xmlProcessingContext.LeaveRunningLocation();
        }
        /// <summary>
        /// Used for parsing short-hand array specification in composition XML.
        /// </summary>
        public static Array ParseArray(IEnumerable <XmlAttribute> attributes, XmlElement[] childElements, XmlProcessingContext context)
        {
            string elementType = null;

            foreach (var attribute in attributes)
            {
                if (attribute.Name == "arrayElementType")
                {
                    elementType = attribute.Value;
                }
                else
                {
                    context.ReportError(string.Format("Attribute name {0} is not supported for array value elements.", attribute.Name));
                    return(null);
                }
            }

            if (elementType == null)
            {
                context.ReportError("Attribute 'arrayElementType' is required.");
                return(null);
            }

            return(ParseArray(elementType, childElements, context));
        }
        /// <summary>
        /// Parses an Assembly element in the composition XML.
        /// </summary>
        public static Assembly ParseAssembly(XmlElement element, XmlProcessingContext context)
        {
            if (element.ChildNodes.Count > 0)
            {
                context.ReportError("Type elements should not contain any child elements.");
                return(null);
            }

            string assemblyName = null;

            if (element.Attributes["name"] != null)
            {
                assemblyName = element.Attributes["name"].Value;
            }

            var result = ParseAssembly(assemblyName, context);

            if (result == null)
            {
                context.EnterRunningLocation(string.Format("Assembly({0})", assemblyName));
                context.ReportError("Could not load assembly '" + assemblyName + "'.");
                context.LeaveRunningLocation();
                return(null);
            }

            return(result);
        }
        /// <summary>
        /// Parses a Ref specification in the short-hand form from a
        /// composition XML.
        /// </summary>
        public static object ParseRef(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string refType = null;
            string refName = null;

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "refType":
                    refType = attribute.Value;
                    break;

                case "refName":
                    refName = attribute.Value;
                    break;

                default:
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for ref value elements.", attribute.Name));
                    return(null);
                }
            }

            if (refType == null)
            {
                context.ReportError("Attribute 'refType' is required.");
                return(null);
            }

            return(ParseRef(refType, refName, context));
        }
        private static void ParseObjectField(object result, XmlElement childElement, XmlProcessingContext xmlProcessingContext)
        {
            if (childElement.Attributes["name"] == null)
            {
                xmlProcessingContext.ReportError("'Field' element in the composition XML should have a 'name' attribute.");
                return;
            }

            var fieldName = childElement.Attributes["name"].Value;

            xmlProcessingContext.EnterRunningLocation(string.Format("Field({0})", fieldName));

            var fieldInfo = result.GetType().GetField(fieldName);

            if (fieldInfo == null)
            {
                xmlProcessingContext.ReportError(
                    string.Format("Object type '{0}' does not contain a field definition named '{1}", result.GetType().FullName,
                                  fieldName));
                xmlProcessingContext.LeaveRunningLocation();
                return;
            }

            var fieldValue = XmlValueParser.ParseValue(childElement, xmlProcessingContext, objectFieldExcludedAttributes);

            fieldInfo.SetValue(result, fieldValue);

            xmlProcessingContext.LeaveRunningLocation();
        }
        /// <summary>
        /// Actually parses an Enum specification in the composition XML, and
        /// is used in both element form, and short-hand forms.
        /// </summary>
        public static object ParseEnum(string enumTypeName, string enumValue, XmlProcessingContext context)
        {
            if (enumTypeName == null)
            {
                throw new ArgumentNullException("enumTypeName");
            }

            if (enumValue == null)
            {
                throw new ArgumentNullException("enumValue");
            }

            context.EnterRunningLocation(string.Format("enum({0}, {1})", enumTypeName, enumValue));

            var enumType = ParseType(enumTypeName, context);

            if (enumType == null)
            {
                context.ReportError(string.Format("Type '{0}' could not be loaded.", enumTypeName));
                return(null);
            }

            if (!enumType.IsValueType)
            {
                context.ReportError(
                    string.Format("Type '{0}' is not an enumeration type, and can not be used in <EnumValue> tag.", enumType));
                return(null);
            }

            var result = Enum.Parse(enumType, enumValue);

            context.LeaveRunningLocation();

            return(result);
        }
        /// <summary>
        /// Parses an enum value in its short-hand form in composition XML.
        /// </summary>
        public static object ParseEnum(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string enumType  = null;
            string enumValue = null;

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "enumType":
                    enumType = attribute.Value;
                    break;

                case "enumValue":
                    enumValue = attribute.Value;
                    break;

                default:
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for enum value elements.", attribute.Name));
                    return(null);
                }
            }

            if ((enumValue == null) || (enumType == null))
            {
                context.ReportError("Both 'enumType' and 'enumValue' attributes are required.");
                return(null);
            }

            return(ParseEnum(enumType, enumValue, context));
        }
        public static byte[] ParseByteArray(string value, XmlProcessingContext context)
        {
            var filteredString = "";

            // remove all none A-F, 0-9, characters
            for (var i = 0; i < value.Length; i++)
            {
                var c = value[i];

                if ((char.IsWhiteSpace(c)) ||
                    (c == '-') ||
                    (c == '_'))
                {
                    continue;
                }

                if (!char.IsLetterOrDigit(c))
                {
                    context.ReportError("Character is not allowed in a hex string: '" + c + "', ignoring.");
                    continue;
                }

                c = char.ToUpper(c);

                if ((char.IsLetter(c)) && ((c > 'F') || (c < 'A')))
                {
                    context.ReportError("Character is not allowed in a hex string: '" + c + "', ignoring.");
                    continue;
                }

                filteredString += c;
            }

            // if odd number of characters, add a zero to the beginning
            if (filteredString.Length % 2 != 0)
            {
                filteredString = "0" + filteredString;
            }

            var byteLength = filteredString.Length / 2;
            var result     = new byte[byteLength];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = byte.Parse(filteredString.Substring(i << 1, 2), NumberStyles.HexNumber);
            }

            return(result);
        }
        /// <summary>
        /// Used for parsing short-hand specification of dictionaries in
        /// the composition XML.
        /// </summary>
        public static IDictionary ParseDictionary(IEnumerable <XmlAttribute> attributes, XmlElement[] childElements,
                                                  XmlProcessingContext context)
        {
            string keyType   = null;
            string valueType = null;

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "dictionaryKeyType":
                    keyType = attribute.Value;
                    break;

                case "dictionaryValueType":
                    valueType = attribute.Value;
                    break;

                default:
                    context.ReportError(string.Format("Attribute name {0} is not supported for array value elements.", attribute.Name));
                    return(null);
                }
            }

            return(ParseDictionary(keyType, valueType, childElements, context));
        }
        /// <summary>
        /// Actually parses an array, and is used in both short-hand and separate
        /// element formats of array specification.
        /// </summary>
        public static Array ParseArray(string elementTypeName, XmlElement[] childElements, XmlProcessingContext context)
        {
            context.EnterRunningLocation(string.Format("Array({0})", elementTypeName ?? "object"));

            var elementType = typeof(object);

            if (elementTypeName != null)
            {
                elementType = SimpleTypeParserUtil.ParseType(elementTypeName, context);
                if (elementType == null)
                {
                    context.ReportError(string.Format("Type '{0}' could not be loaded.", elementTypeName));
                    return(null);
                }
            }

            var arrayElements = GetCollectionElements(childElements, elementType, context);

            var result = Array.CreateInstance(elementType, arrayElements.Count);

            for (var i = 0; i < result.Length; i++)
            {
                result.SetValue(arrayElements[i], i);
            }

            context.LeaveRunningLocation();

            return(result);
        }
        /// <summary>
        /// Used for parsing an Object element in the composition XML.
        /// </summary>
        public static object ParseObject(XmlElement element, XmlProcessingContext context)
        {
            string typeName        = null;
            var    initializePlugs = false;

            if (element.Attributes["type"] != null)
            {
                typeName = element.Attributes["type"].Value;
            }

            if (element.Attributes["initializePlugs"] != null)
            {
                initializePlugs = Boolean.Parse(element.Attributes["initializePlugs"].Value);
            }

            if (typeName == null)
            {
                context.ReportError("'Object' element in the composition XML should have a 'type' attribute.");
                return(null);
            }

            var childElements = new List <XmlElement>();

            foreach (XmlNode childNode in element.ChildNodes)
            {
                if (childNode is XmlElement)
                {
                    childElements.Add((XmlElement)childNode);
                }
            }

            return(ParseObject(typeName, initializePlugs, childElements.ToArray(), context));
        }
        /// <summary>
        /// Actually parses the contents of lists from composition XMLs, and is
        /// used in both short-hand form and complete form of list specification.
        /// </summary>
        public static IList ParseList(string elementTypeName, XmlElement[] childElements, XmlProcessingContext context)
        {
            context.EnterRunningLocation(string.Format("List({0})", elementTypeName ?? "object"));

            var elementType = typeof(object);

            if (elementTypeName != null)
            {
                elementType = SimpleTypeParserUtil.ParseType(elementTypeName, context);
                if (elementType == null)
                {
                    context.ReportError(string.Format("Type '{0}' could not be loaded.", elementTypeName));
                    context.LeaveRunningLocation();
                    return(null);
                }
            }

            var listElements = GetCollectionElements(childElements, elementType, context);

            var listType = Type.GetType(string.Format("System.Collections.Generic.List`1[[{0}]]",
                                                      elementType.AssemblyQualifiedName));

            var result = (IList)Activator.CreateInstance(listType);

            foreach (var o in listElements)
            {
                result.Add(o);
            }

            context.LeaveRunningLocation();

            return(result);
        }
        internal static void ProcessCompositionXml(Stream configurationStream, XmlProcessingContext xmlProcessingContext)
        {
            if (configurationStream == null)
            {
                throw new ArgumentNullException(nameof(configurationStream));
            }

            var xsdStream =
                typeof(AssemblyPointer).Assembly.GetManifestResourceStream(
                    "ComposerCore.CompositionXml.Schema.compositionXml.1.0.xsd");

            if (xsdStream == null)
            {
                throw new NullReferenceException("Could not load XSD resource from DLL.");
            }

            var schema =
                XmlSchema.Read(
                    xsdStream,
                    (sender, e) => throw new CompositionXmlValidationException(
                        "Could not load XSD for Composition XML. Message: " + e.Message + "; Sender: " +
                        sender, e.Exception));

            var schemaSet = new XmlSchemaSet();

            schemaSet.Add(schema);

            var settings = new XmlReaderSettings {
                ValidationType = ValidationType.Schema, Schemas = schemaSet
            };

            settings.ValidationEventHandler += delegate(object sender, ValidationEventArgs e)
            {
                var errorMessage = "Composition XML Schema Validation error: ";

                if (e.Exception is XmlSchemaValidationException validationException)
                {
                    errorMessage += "Line: " + validationException.LineNumber + ", Position: " +
                                    validationException.LinePosition +
                                    "; " + validationException.Message;
                }
                else
                {
                    errorMessage += "Message: " + e.Message + "; Sender: " + sender +
                                    "; Inner exception: " + e.Exception.Message;
                }

                xmlProcessingContext.ReportError(errorMessage);
            };

            var serializer = new XmlSerializer(typeof(CompositionInfo));

            var reader = XmlReader.Create(configurationStream, settings);
            var info   = (CompositionInfo)serializer.Deserialize(reader);

            info.Validate();

            CompositionInfoApplicator.ApplyCompositionInfo(info, xmlProcessingContext);
        }
        /// <summary>
        /// Parses a contentsOfVariableName specification in composition XML in its short-hand form.
        /// </summary>
        public static object ParseTimeSpan(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            // Declare variables for possible input values
            string timeSpanString = null;
            int?   days           = null;
            int?   hours          = null;
            int?   minutes        = null;
            int?   seconds        = null;
            int?   milliseconds   = null;
            long?  ticks          = null;

            // Extract input values from the attributes (can be in any order)

            foreach (var attribute in attributes)
            {
                switch (attribute.Name)
                {
                case "timeSpan":
                    timeSpanString = attribute.Value;
                    break;

                case "timeSpanDays":
                    days = Int32.Parse(attribute.Value);
                    break;

                case "timeSpanHours":
                    hours = Int32.Parse(attribute.Value);
                    break;

                case "timeSpanMinutes":
                    minutes = Int32.Parse(attribute.Value);
                    break;

                case "timeSpanSeconds":
                    seconds = Int32.Parse(attribute.Value);
                    break;

                case "timeSpanMilliseconds":
                    milliseconds = Int32.Parse(attribute.Value);
                    break;

                case "timeSpanTicks":
                    ticks = Int64.Parse(attribute.Value);
                    break;

                default:
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for timeSpan value elements.", attribute.Name));
                    return(null);
                }
            }

            // Validate and parse the extracted values

            return(ParseTimeSpan(timeSpanString, days, hours, minutes, seconds, milliseconds, ticks, context));
        }
        private static List <object> GetCollectionElements(XmlElement[] xmlElements, Type elementType,
                                                           XmlProcessingContext xmlProcessingContext)
        {
            var arrayElements = new List <object>();

            for (var i = 0; i < xmlElements.Length; i++)
            {
                xmlProcessingContext.EnterRunningLocation(string.Format("Item({0})", i));

                var childElement = xmlElements[i];

                if (childElement.Name == "Item")
                {
                    var arrayElement = XmlValueParser.ParseValue(childElement, xmlProcessingContext, null);

                    if ((arrayElement != null) && (!elementType.IsInstanceOfType(arrayElement)))
                    {
                        xmlProcessingContext.ReportError(
                            string.Format("Array of the element type {0} can not contain items with type {1}.", elementType.FullName,
                                          arrayElement.GetType().FullName));
                        xmlProcessingContext.LeaveRunningLocation();
                        return(null);
                    }

                    arrayElements.Add(arrayElement);
                }
                else
                {
                    xmlProcessingContext.ReportError(
                        string.Format("Xml element '{0}' is not allowed in 'Array' element - type: {1}[]", childElement.Name,
                                      elementType.FullName));
                    xmlProcessingContext.LeaveRunningLocation();
                    return(null);
                }

                xmlProcessingContext.LeaveRunningLocation();
            }

            return(arrayElements);
        }
        private static object[] ParseConstructorArgs(XmlElement element,
                                                     XmlProcessingContext xmlProcessingContext)
        {
            if (element.Name != "ConstructorArgs")
            {
                throw new ArgumentException("Calling this method is only valid for 'ConstructorArgs' element.");
            }

            if (element.HasAttributes)
            {
                xmlProcessingContext.ReportError("'ConstructorArgs' element should not have any attributes.");
            }

            xmlProcessingContext.EnterRunningLocation("ConstructorArgs");

            var result = new List <object>();

            foreach (XmlNode childNode in element.ChildNodes)
            {
                var childElement = childNode as XmlElement;
                if (childElement == null)
                {
                    continue;
                }

                if (childElement.Name == "Arg")
                {
                    result.Add(XmlValueParser.ParseValue(childElement, xmlProcessingContext, null));
                }
                else
                {
                    xmlProcessingContext.ReportError(
                        string.Format("Element '{0}' is not allowed in the 'ConstructorArgs' element.", childElement.Name));
                }
            }

            xmlProcessingContext.LeaveRunningLocation();
            return(result.ToArray());
        }
Example #22
0
        internal static void ProcessCompositionXmlFromResource(Assembly assembly, string configurationResourceName,
                                                               XmlProcessingContext xmlProcessingContext)
        {
            var stream = assembly.GetManifestResourceStream(configurationResourceName);

            if (stream == null)
            {
                xmlProcessingContext.ReportError($"Resource name '{configurationResourceName}' could not be loaded from assembly '{assembly.FullName}'.");
                return;
            }

            ProcessCompositionXml(stream, xmlProcessingContext);
        }
        /// <summary>
        /// Parses a ContentsOfVariable element in the composition XML.
        /// </summary>
        public static object ParseContentsOfVariable(XmlElement element, XmlProcessingContext context)
        {
            if (element.ChildNodes.Count > 0)
            {
                context.ReportError("'ContentsOfVariable' elements should not contain any child elements.");
                return(null);
            }

            string variableName = null;

            if (element.Attributes["name"] != null)
            {
                variableName = element.Attributes["name"].Value;
            }

            if (variableName == null)
            {
                context.ReportError("'ContentsOfVariable' elements require a 'name' attribute.");
                return(null);
            }

            return(ParseContentsOfVariable(variableName, context));
        }
        /// <summary>
        /// Parses an assembly specification in composition XML in its short-hand form.
        /// </summary>
        public static Assembly ParseAssembly(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string assemblyName = null;

            foreach (var attribute in attributes)
            {
                if (attribute.Name == "assemblyName")
                {
                    assemblyName = attribute.Value;
                }
                else
                {
                    context.ReportError(
                        string.Format("Attribute name {0} is not supported for assembly value elements.", attribute.Name));
                    return(null);
                }
            }

            if (assemblyName == null)
            {
                context.ReportError("Attribute 'assemblyName' is required.");
                return(null);
            }

            var result = ParseAssembly(assemblyName, context);

            if (result == null)
            {
                context.EnterRunningLocation(string.Format("Assembly({0})", assemblyName));
                context.ReportError("Could not load assembly '" + assemblyName + "'.");
                context.LeaveRunningLocation();
                return(null);
            }


            return(result);
        }
        /// <summary>
        /// Parses a type specification in composition XML in its short-hand form.
        /// </summary>
        public static Type ParseType(IEnumerable <XmlAttribute> attributes, XmlProcessingContext context)
        {
            string typeName = null;

            foreach (var attribute in attributes)
            {
                if (attribute.Name == "typeName")
                {
                    typeName = attribute.Value;
                }
                else
                {
                    context.ReportError(string.Format("Attribute name {0} is not supported for type value elements.", attribute.Name));
                    return(null);
                }
            }

            if (typeName == null)
            {
                context.ReportError("Attribute 'typeName' is required.");
                return(null);
            }

            var result = ParseType(typeName, context);

            if (result == null)
            {
                context.EnterRunningLocation(string.Format("Type({0})", typeName));
                context.ReportError("Could not load type '" + typeName + "'.");
                context.LeaveRunningLocation();
                return(null);
            }


            return(result);
        }
Example #26
0
        internal static void ProcessCompositionXml(string configurationPath, XmlProcessingContext xmlProcessingContext)
        {
            if (configurationPath == null)
            {
                throw new ArgumentNullException(nameof(configurationPath));
            }

            if (!File.Exists(configurationPath))
            {
                xmlProcessingContext.ReportError($"Specified configuration file '{configurationPath}' does not exist.");
                return;
            }

            using (Stream configurationStream = File.Open(configurationPath, FileMode.Open, FileAccess.Read))
            {
                ProcessCompositionXml(configurationStream, xmlProcessingContext);
            }
        }
        /// <summary>
        /// Parses a Ref element in the composition XML.
        /// </summary>
        public static object ParseRef(XmlElement element, XmlProcessingContext context)
        {
            if (element.ChildNodes.Count > 0)
            {
                context.ReportError("Ref elements should not contain any child elements.");
                return(null);
            }

            string refType = null;
            string refName = null;

            if (element.Attributes["type"] != null)
            {
                refType = element.Attributes["type"].Value;
            }

            if (element.Attributes["name"] != null)
            {
                refName = element.Attributes["name"].Value;
            }

            return(ParseRef(refType, refName, context));
        }
        /// <summary>
        /// Actually parses the contents on Ref specification in composition XML.
        /// Looks up the referenced component in the component context, and returns the result.
        /// Is used both in short-hand form and element form on Ref specification.
        /// </summary>
        public static object ParseRef(string refTypeName, string refName, XmlProcessingContext context)
        {
            if (refTypeName == null)
            {
                throw new ArgumentNullException("refTypeName");
            }

            context.EnterRunningLocation(string.Format("Ref({0})", refTypeName));

            var refType = ParseType(refTypeName, context);

            if (refType == null)
            {
                context.ReportError(string.Format("Type '{0}' could not be loaded.", refTypeName));
                return(null);
            }

            var result = context.ComponentContext.GetComponent(refType, refName);

            context.LeaveRunningLocation();

            return(result);
        }
        /// <summary>
        /// Parses an Enum element in a composition XML.
        /// </summary>
        public static object ParseEnum(XmlElement element, XmlProcessingContext context)
        {
            if (element.ChildNodes.Count > 0)
            {
                context.ReportError("Enum elements should not contain any child elements.");
                return(null);
            }

            string enumTypeName = null;
            string enumValue    = null;

            if (element.Attributes["type"] != null)
            {
                enumTypeName = element.Attributes["type"].Value;
            }

            if (element.Attributes["value"] != null)
            {
                enumValue = element.Attributes["value"].Value;
            }

            return(ParseEnum(enumTypeName, enumValue, context));
        }
        /// <summary>
        /// Actually parses the object and returns the result. Used both in short-hand
        /// form and in direct Object element parsing.
        /// </summary>
        public static object ParseObject(string typeName, bool initializePlugs, XmlElement[] childElements,
                                         XmlProcessingContext context)
        {
            context.EnterRunningLocation(string.Format("Object({0})", typeName));

            // Look for constructor arguments.
            // Set default to null, so that Activator calls default constructor
            // in case the the "ConstructorArgs" element is not specified.

            object[] constructorArguments = null;

            foreach (var childElement in childElements)
            {
                if (childElement.Name != "ConstructorArgs")
                {
                    continue;
                }
                // Check if this is the second "ConstructorArgs" element.
                // If so, report an error and return.

                if (constructorArguments != null)
                {
                    context.ReportError("The 'ConstructorArgs' element can be specified maximum once in an 'Object' element.");
                    context.LeaveRunningLocation();
                    return(null);
                }

                constructorArguments = ParseConstructorArgs(childElement, context);
                context.ThrowIfErrors();
            }

            // Resolve the "Type" for the object to be instantiated

            var objectType = SimpleTypeParserUtil.ParseType(typeName, context);

            if (objectType == null)
            {
                context.ReportError(string.Format("Type '{0}' could not be loaded.", typeName));
                context.LeaveRunningLocation();
                return(null);
            }

            // Use Activator class to instantiate the object

            var result = Activator.CreateInstance(objectType, constructorArguments);

            if (initializePlugs)
            {
                context.ComponentContext.InitializePlugs(result, objectType);
            }

            foreach (var childElement in childElements)
            {
                switch (childElement.Name)
                {
                case "ConstructorArgs":
                    break;

                case "Property":
                    ParseObjectProperty(result, childElement, context);
                    break;

                case "Field":
                    ParseObjectField(result, childElement, context);
                    break;

                default:                                // Also: case "ConstructorArgs"
                    context.ReportError(
                        string.Format("Xml element '{0}' is not allowed in 'Object' element - type: {1}", childElement.Name,
                                      typeName));
                    context.LeaveRunningLocation();
                    return(null);
                }
            }

            context.LeaveRunningLocation();
            return(result);
        }