UiLoadedObject ParseObjectInternal( Type objType, XElement el, List <XmlObjectMap> objectMaps, Dictionary <string, InterfaceColor> interfaceColors, Dictionary <string, InterfaceModel> interfaceModels, Dictionary <string, InterfaceImage> interfaceImages ) { UiXmlReflection.GetProperties( objType, out Dictionary <string, PropertyInfo> elements, out Dictionary <string, PropertyInfo> attributes, out PropertyInfo contentProperty, out PropertyInfo reinitProperty ); var result = new UiLoadedObject(objType); List <UiLoadedObject> contentObjects = null; bool isContentList = false; if (contentProperty != null) { isContentList = Activator.CreateInstance(contentProperty.PropertyType) is IList; if (isContentList) { contentObjects = new List <UiLoadedObject>(); } } if (reinitProperty != null) { result.Setters.Add(new UiSimpleProperty(reinitProperty, new UiRecreateHandle(result))); } if (objectMaps != null) { var li = (IXmlLineInfo)el; objectMaps.Add(new XmlObjectMap() { Line = li.LineNumber, Column = li.LinePosition, Element = el, Object = result }); } foreach (var attr in el.Attributes()) { var pname = attr.Name.ToString(); PropertyInfo property; if (attributes.TryGetValue(pname, out property)) { object value = null; var ptype = property.PropertyType; if (ptype.IsEnum) { value = Enum.Parse(ptype, attr.Value, true); } else if (ptype == typeof(InterfaceColor)) { InterfaceColor color; if (!interfaceColors.TryGetValue(attr.Value, out color)) { color = new InterfaceColor() { Color = Parser.Color(attr.Value) }; } value = color; } else if (ptype == typeof(InterfaceModel) && interfaceModels.TryGetValue(attr.Value, out var model)) { value = model; } else if (ptype == typeof(InterfaceImage) && interfaceImages.TryGetValue(attr.Value, out var image)) { value = image; } else if (ptype == typeof(string)) { value = attr.Value; } else { value = Convert.ChangeType(attr.Value, ptype, CultureInfo.InvariantCulture); } result.Setters.Add(new UiSimpleProperty(property, value)); } else { //Throw error? } } foreach (var child in el.Elements()) { var childName = child.Name.ToString(); PropertyInfo property = null; if (childName.Contains(".")) { childName = childName.Split('.')[1]; if (!elements.TryGetValue(childName, out property)) { throw new Exception($"{el.Name} does not have property {childName}"); } } if (property != null) { var v = Activator.CreateInstance(property.PropertyType); if (v is IList list) { var listType = property.PropertyType.GenericTypeArguments[0]; if (PrimitiveList(property, child, listType, out var primlist)) { result.Setters.Add(primlist); } else { var objs = new List <UiLoadedObject>(); foreach (var itemXml in child.Elements()) { var nt = UiXmlReflection.Instantiate(itemXml.Name.ToString()).GetType(); objs.Add(ParseObjectInternal(nt, itemXml, objectMaps, interfaceColors, interfaceModels, interfaceImages)); } result.Setters.Add(new UiComplexList(property, objs.ToArray())); } } else if (v is IDictionary dict) { var keyType = property.PropertyType.GenericTypeArguments[0]; var valueType = property.PropertyType.GenericTypeArguments[1]; if (PrimitiveDictionary(child, property, keyType, valueType, out var primdict)) { result.Setters.Add(primdict); } else { var keys = new List <object>(); var values = new List <UiLoadedObject>(); foreach (var itemXml in child.Elements()) { var nt = UiXmlReflection.Instantiate(itemXml.Name.ToString()).GetType(); values.Add(ParseObjectInternal(nt, itemXml, objectMaps, interfaceColors, interfaceModels, interfaceImages)); keys.Add(GetDictionaryKey(itemXml, keyType)); } result.Setters.Add(new UiComplexDictionary(property, keys.ToArray(), values.ToArray())); } } else if (property.SetMethod != null) { var obj = ParseObjectInternal(property.PropertyType, child, objectMaps, interfaceColors, interfaceModels, interfaceImages); result.Setters.Add(new UiComplexProperty(property, obj)); } } else { if (contentProperty == null) { throw new Exception($"{objType.FullName} lacks UiContentAttribute property"); } var nt = UiXmlReflection.Instantiate(child.Name.ToString()).GetType(); var content = ParseObjectInternal(nt, child, objectMaps, interfaceColors, interfaceModels, interfaceImages); if (isContentList) { contentObjects.Add(content); } else { result.Setters.Add(new UiComplexProperty(contentProperty, content)); } } if (objectMaps != null) { var nEnd = child.NodesAfterSelf().FirstOrDefault(); var li = (IXmlLineInfo)nEnd; objectMaps.Add(new XmlObjectMap() { Line = li.LineNumber, Column = li.LinePosition, Object = result }); } } if (isContentList) { result.Setters.Add(new UiComplexList(contentProperty, contentObjects.ToArray())); } return(result); }
public UiComplexProperty(PropertyInfo p, UiLoadedObject v) : base(p) { Value = v; }
internal UiRecreateHandle(UiLoadedObject loaded) { this.loaded = loaded; }