private static void FillDataToCollection(XmlReader reader, object objectData, Dictionary <string, Type> typeMapping, Type elementType, Type parentType) { const string addMethodName = "Add"; int currentDepth = reader.Depth; bool isValueType = elementType.IsValueType || typeof(string).Equals(elementType) || elementType.IsEnum; // Type genericType = rawType.GetGenericArguments()[0]; Type genericType = ModuleUtils.GetRawGenericElementType(parentType); MethodInfo addMethod = parentType.GetMethod(addMethodName, BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { genericType }, new ParameterModifier[0]); GenericCollectionAttribute collectionAttribute = elementType.GetCustomAttribute <GenericCollectionAttribute>(); reader.Read(); // xml层级等于或者小于父节点时说明集合已经遍历结束,停止遍历 // Reader的更新在Read while (reader.Depth > currentDepth) { // 如果不是节点或者是空节点或者是结束节点,则继续下一行读取 if (reader.NodeType != XmlNodeType.Element || (reader.IsEmptyElement && !reader.HasAttributes) || reader.NodeType == XmlNodeType.EndElement) { bool readNotOver = reader.Read(); if (!readNotOver) { return; } continue; } if (isValueType) { string value = reader.GetAttribute(Constants.ValueTypeName); if (null != value) { object element = ValueConvertor.ReadData(elementType, value); addMethod.Invoke(objectData, new object[] { element }); } // Value模式时需要手动去调整reader的位置 reader.Read(); } else { // 填充集合或者类时,reader的shift在FillDataToObject和FillDataToCollection中调用 object element = CreateTypeInstance(typeMapping, GetTypeName(elementType)); if (null == collectionAttribute) { FillDataToObject(reader, element, typeMapping); } else { FillDataToCollection(reader, element, typeMapping, collectionAttribute.GenericType, genericType); } addMethod.Invoke(objectData, new object[] { element }); } } // 如果是endElement则直接跳过 if (reader.NodeType == XmlNodeType.EndElement) { reader.Read(); } }
// 处理一个类的所有属性反序列化。如果当前深度大于等于父级的深度,则说明已经走到了当前项的最后一行,如果这行是EndElement,则read,跳转到下一行。 // 读取顺序:进入某个Element后,先检查所有的Attribute,填充到对象中;然后跳到下一行。 // 如果下个 private static void FillDataToObject(XmlReader reader, object objectData, Dictionary <string, Type> typeMapping) { int currentDepth = reader.Depth; Type dataType = typeMapping[GetTypeName(objectData.GetType())]; if (reader.HasAttributes) { foreach (PropertyInfo propertyInfo in dataType.GetProperties()) { string propertyName = GetTypeName(propertyInfo.PropertyType); Type propertyType = typeMapping.ContainsKey(propertyName) ? typeMapping[propertyName] : propertyInfo.PropertyType; SerializationIgnoreAttribute ignoreAttribute = propertyInfo.GetCustomAttribute <SerializationIgnoreAttribute>(); GenericCollectionAttribute collectionAttribute = propertyType.GetCustomAttribute <GenericCollectionAttribute>(); // 值类型、字符串、枚举类型,并且未被ignore的非集合属性直接用值转换器处理 if ((propertyInfo.PropertyType.IsValueType || typeof(string).Equals(propertyInfo.PropertyType) || propertyInfo.PropertyType.IsEnum) && null == ignoreAttribute && null == collectionAttribute) { string attribute = reader.GetAttribute(propertyInfo.Name); if (null == attribute) { continue; } FillValueToObject(propertyInfo, objectData, attribute); } } } int propertyNodeDepth = currentDepth + 1; bool readNotOver = reader.Read(); if (!readNotOver) { return; } // xml层级等于或者小于父节点时应该交给上一层的调用处理 while (reader.Depth > currentDepth) { // 如果不是节点或者是空节点或者是结束节点,则继续下一行读取 if (reader.NodeType != XmlNodeType.Element || (reader.IsEmptyElement && !reader.HasAttributes) || reader.NodeType == XmlNodeType.EndElement) { readNotOver = reader.Read(); if (!readNotOver) { return; } continue; } string propertyName = reader.Name; PropertyInfo propertyInfo = dataType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public); string propertyTypeName = GetTypeName(propertyInfo.PropertyType); if (reader.Depth != propertyNodeDepth || null == propertyInfo || !typeMapping.ContainsKey(propertyTypeName)) { I18N i18N = I18N.GetInstance(Constants.I18nName); throw new TestflowDataException(ModuleErrorCode.DeSerializeFailed, i18N.GetStr("IllegalFileData")); } object propertyObject = CreateTypeInstance(typeMapping, propertyTypeName); propertyInfo.SetValue(objectData, propertyObject); Type propertyType = typeMapping[propertyTypeName]; GenericCollectionAttribute collectionAttribute = propertyType.GetCustomAttribute <GenericCollectionAttribute>(); if (null == collectionAttribute) { FillDataToObject(reader, propertyObject, typeMapping); } else { FillDataToCollection(reader, propertyObject, typeMapping, collectionAttribute.GenericType, propertyObject.GetType()); } } if (reader.NodeType == XmlNodeType.EndElement) { reader.Read(); } }
private static void WriteClassData(string dataName, object dataValue, XmlWriter writer) { // 如果属性为null则返回不写入内容 if (null == dataValue) { return; } writer.WriteStartElement(dataName); Type dataType = dataValue.GetType(); List <PropertyInfo> collectionProperties = new List <PropertyInfo>(10); List <Type> collectionElemType = new List <Type>(10); List <PropertyInfo> classProperties = new List <PropertyInfo>(10); SerializationOrderEnableAttribute orderEnableAttr = dataType.GetCustomAttribute <SerializationOrderEnableAttribute>(); PropertyInfo[] properties = dataType.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo propertyInfo in properties) { object propertyValue = propertyInfo.GetValue(dataValue); if (null == propertyValue) { continue; } Type propertyType = propertyValue.GetType(); XmlIgnoreAttribute xmlIgnoreAttribute = propertyInfo.GetCustomAttribute <XmlIgnoreAttribute>(); SerializationIgnoreAttribute ignoreAttribute = propertyInfo.GetCustomAttribute <SerializationIgnoreAttribute>(); GenericCollectionAttribute collectionAttribute = propertyType.GetCustomAttribute <GenericCollectionAttribute>(); if (null != xmlIgnoreAttribute || (null != ignoreAttribute && ignoreAttribute.Ignore)) { continue; } // 集合类型的数据和类类型的数据在后面写入 if (null != collectionAttribute) { collectionProperties.Add(propertyInfo); collectionElemType.Add(collectionAttribute.GenericType); } else if (propertyType.IsClass && !typeof(string).Equals(propertyType)) { classProperties.Add(propertyInfo); } else if (propertyType.IsEnum) { WriteValueData(propertyInfo.Name, propertyValue.ToString(), writer); } else { WriteValueData(propertyInfo.Name, propertyValue, writer); } } // 如果该对象需要对属性进行排序写入,则先写入已配置顺序的属性 if (null != orderEnableAttr && orderEnableAttr.OrderEnable) { WriteOrderEnabledProperties(dataValue, writer, collectionProperties, collectionElemType, classProperties); } // 写入类信息 foreach (PropertyInfo propertyInfo in classProperties) { WriteClassData(propertyInfo.Name, propertyInfo.GetValue(dataValue), writer); } // 写入集合信息 for (int i = 0; i < collectionProperties.Count; i++) { WriteCollectionData(collectionProperties[i].Name, collectionProperties[i].GetValue(dataValue), collectionElemType[i], writer); } writer.WriteEndElement(); }