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); }
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(); }
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 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); }
/// <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> /// 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> /// 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); }
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); }
/// <summary> /// Actually parses contentsOfVariable string, looking up the variable name. Used in /// both short-hand form and element form of contentsOfVariable specification. /// </summary> public static object ParseContentsOfVariable(string variableName, XmlProcessingContext context) { if (variableName == null) { throw new ArgumentNullException("variableName"); } context.EnterRunningLocation(string.Format("Parsing ContentsOfVariable({0})", variableName)); var result = context.ComponentContext.GetVariable(variableName); context.LeaveRunningLocation(); return(result); }
/// <summary> /// Parses a SerializeBinary element in the composition XML. /// </summary> public static object ParseSerializeBinary(XmlElement element, XmlProcessingContext context) { context.EnterRunningLocation("SerializeBinary"); var serializableValue = XmlValueParser.ParseValue(element, context, null); var formatter = new BinaryFormatter(); var stream = new MemoryStream(); formatter.Serialize(stream, serializableValue); var result = stream.ToArray(); stream.Close(); context.LeaveRunningLocation(); return(result); }
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()); }
/// <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 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); }
/// <summary> /// Validates the raw values extracted from a TimeSpan element or TimeSpan related /// attributes, and then extracts and returns the actual value. /// </summary> public static object ParseTimeSpan(string timeSpanString, int?days, int?hours, int?minutes, int?seconds, int?milliseconds, long?ticks, XmlProcessingContext context) { object result; context.EnterRunningLocation("TimeSpan"); // Validate the entered values: // Should not specify "ticks" with anything else, // Should not specify "timeSpanString" with anything else, // Should have at least one value specified. if (timeSpanString != null) { if ((ticks.HasValue) || (days.HasValue) || (hours.HasValue) || (minutes.HasValue) || (seconds.HasValue) || (milliseconds.HasValue)) { context.ReportError("Cannot specify any other attribute for TimeSpan when the 'string' to be parsed is specified."); context.LeaveRunningLocation(); return(null); } } if (ticks.HasValue) { if ((days.HasValue) || (hours.HasValue) || (minutes.HasValue) || (seconds.HasValue) || (milliseconds.HasValue)) { context.ReportError("Cannot specify any other attribute for TimeSpan when the ticks is specified."); context.LeaveRunningLocation(); return(null); } } if ((timeSpanString == null) && (!ticks.HasValue) && (!days.HasValue) && (!hours.HasValue) && (!minutes.HasValue) && (!seconds.HasValue) && (!milliseconds.HasValue)) { context.ReportError("Should specify at least one of the attributes for the TimeSpan value node."); context.LeaveRunningLocation(); return(null); } // If string is specified, use it to parse the TimeSpan and return. if (timeSpanString != null) { result = ParseTimeSpan(timeSpanString); context.LeaveRunningLocation(); return(result); } // If ticks is specified, use it to parse the TimeSpan and return. if (ticks.HasValue) { result = ParseTimeSpan(ticks.Value); context.LeaveRunningLocation(); return(result); } // Use days/hours/minutes/seconds/milliseconds to create the TimeSpan, and // Set every un-specified values to zero, in order to prevent NullReferenceException. if (!days.HasValue) { days = 0; } if (!hours.HasValue) { hours = 0; } if (!minutes.HasValue) { minutes = 0; } if (!seconds.HasValue) { seconds = 0; } if (!milliseconds.HasValue) { milliseconds = 0; } result = ParseTimeSpan(days.Value, hours.Value, minutes.Value, seconds.Value, milliseconds.Value); context.LeaveRunningLocation(); return(result); }
/// <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); }
/// <summary> /// Actually parses the contents of dictionaries in composition XMLs, and is /// used for both short-hand and seperate element formats of dictionary specification. /// </summary> public static IDictionary ParseDictionary(string keyTypeName, string valueTypeName, XmlElement[] xmlElements, XmlProcessingContext context) { context.EnterRunningLocation( string.Format("Parse Dictionary({0}, {1})", keyTypeName ?? "object", valueTypeName ?? "object")); var keyType = typeof(object); var valueType = typeof(object); if (keyTypeName != null) { keyType = SimpleTypeParserUtil.ParseType(keyTypeName, context); if (keyType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", keyTypeName)); context.LeaveRunningLocation(); return(null); } } if (valueTypeName != null) { valueType = SimpleTypeParserUtil.ParseType(valueTypeName, context); if (valueType == null) { context.ReportError(string.Format("Type '{0}' could not be loaded.", valueTypeName)); context.LeaveRunningLocation(); return(null); } } var dictionaryType = Type.GetType(string.Format("System.Collections.Generic.Dictionary`2[[{0}],[{1}]]", keyType.AssemblyQualifiedName, valueType.AssemblyQualifiedName)); var result = (IDictionary)Activator.CreateInstance(dictionaryType); for (var i = 0; i < xmlElements.Length; i++) { var childElement = xmlElements[i]; if (childElement.Name == "Item") { context.EnterRunningLocation(string.Format("Item({0})", i)); ParseDictionaryItem(result, childElement, context); context.LeaveRunningLocation(); // For Item } else { context.ReportError( string.Format("Xml element '{0}' is not allowed in 'Dictionary' element - type: Dictionary<{1}, {2}>", childElement.Name, keyType.FullName, valueType.FullName)); context.LeaveRunningLocation(); return(null); } } context.LeaveRunningLocation(); return(result); }