internal void ReinitObject(object obj, XElement el) { UiXmlReflection.GetProperties( obj.GetType(), out _, out _, out var contentProperty, out _); if (contentProperty != null) { var list = contentProperty.GetValue(obj) as IList; list?.Clear(); } FillObject(obj, el, null); }
public void FillObject(object obj, XElement el, List <XmlObjectMap> objectMaps) { UiXmlReflection.GetProperties( obj.GetType(), out Dictionary <string, PropertyInfo> elements, out Dictionary <string, PropertyInfo> attributes, out PropertyInfo contentProperty, out PropertyInfo reinitProperty ); if (reinitProperty != null) { var handle = new UiRecreateHandle() { Element = el, Object = obj, Loader = this }; reinitProperty.SetValue(obj, handle); } if (objectMaps != null) { var li = (IXmlLineInfo)el; objectMaps.Add(new XmlObjectMap() { Line = li.LineNumber, Column = li.LinePosition, Element = el, Object = obj }); } Dictionary <string, InterfaceColor> interfaceColors = new Dictionary <string, InterfaceColor>(); Dictionary <string, InterfaceModel> interfaceModels = new Dictionary <string, InterfaceModel>(); Dictionary <string, InterfaceImage> interfaceImages = new Dictionary <string, InterfaceImage>(); foreach (var clr in Resources.Colors) { interfaceColors.Add(clr.Name, clr); } foreach (var clr in Resources.Models) { interfaceModels.Add(clr.Name, clr); } foreach (var clr in Resources.Images) { interfaceImages.Add(clr.Name, clr); } 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); } property.SetValue(obj, 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 = property.GetValue(obj); if (v is IList list) { var listType = property.PropertyType.GenericTypeArguments[0]; if (!PrimitiveList(child, list, listType)) { foreach (var itemXml in child.Elements()) { var item = Activator.CreateInstance(listType); FillObject(item, itemXml, objectMaps); list.Add(item); } } } else if (v is IDictionary dict) { var keyType = property.PropertyType.GenericTypeArguments[0]; var valueType = property.PropertyType.GenericTypeArguments[1]; if (!PrimitiveDictionary(child, dict, keyType, valueType)) { foreach (var itemXml in child.Elements()) { var item = Activator.CreateInstance(valueType); FillObject(item, itemXml, objectMaps); var key = GetDictionaryKey(itemXml, keyType); dict[key] = item; } } } else if (property.SetMethod != null) { var newValue = Activator.CreateInstance(property.PropertyType); FillObject(newValue, child, objectMaps); property.SetValue(obj, newValue); } } else { if (contentProperty == null) { throw new Exception($"{obj.GetType().FullName} lacks UiContentAttribute property"); } var content = UiXmlReflection.Instantiate(child.Name.ToString()); FillObject(content, child, objectMaps); var containerValue = contentProperty.GetValue(obj); if (containerValue is IList list) { list.Add(content); } else { contentProperty.SetValue(obj, content); } } if (objectMaps != null) { var nEnd = child.NodesAfterSelf().FirstOrDefault(); var li = (IXmlLineInfo)nEnd; objectMaps.Add(new XmlObjectMap() { Line = li.LineNumber, Column = li.LinePosition, Object = obj }); } } }
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); }