コード例 #1
0
ファイル: XmlReaderHelper.cs プロジェクト: spartajet/Testflow
        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();
            }
        }
コード例 #2
0
ファイル: XmlReaderHelper.cs プロジェクト: spartajet/Testflow
        // 处理一个类的所有属性反序列化。如果当前深度大于等于父级的深度,则说明已经走到了当前项的最后一行,如果这行是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();
            }
        }
コード例 #3
0
        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();
        }