예제 #1
0
        public static XmlDeserializerCache Get(Type type)
        {
            XmlDeserializerCache cache;

            if (_instances.TryGetValue(type, out cache))
            {
                return(cache);
            }

            cache = new XmlDeserializerCache(type);
            _instances.Add(type, cache);
            return(cache);
        }
예제 #2
0
        private object TransverseNode(Type type, XmlNode node, bool listItemSeparated = true)
        {
            object obj;

            if (type.IsPrimitive)
            {
                var parseMethod = type.GetMethod("Parse", new Type[] { typeof(string) });
                obj = parseMethod.Invoke(null, new object[] { node.InnerText });
            }
            else if (type.IsEnum)
            {
                obj = Enum.Parse(type, node.InnerText, true);
            }
            else if (type.Name == "String")
            {
                return(node.InnerText);
            }
            else if (listItemSeparated == false && type.Name == "List`1")
            {
                obj = Activator.CreateInstance(type);

                var argType   = type.GetGenericArguments()[0];
                var addMethod = type.GetMethod("Add");
                var addArg    = new object[] { null };

                foreach (XmlNode childNode in node.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }

                    var childObj = TransverseNode(argType, childNode);

                    addArg[0] = childObj;
                    addMethod.Invoke(obj, addArg);
                }
            }
            else
            {
                var typeCache = XmlDeserializerCache.Get(type);

                if (node.Attributes != null)
                {
                    var specifiedType = node.Attributes?.GetNamedItem("xsi:type") ?? null;
                    if (specifiedType != null)
                    {
                        Type tempType = null;
                        if (typeCache.Includes.TryGetValue(specifiedType.Value, out tempType))
                        {
                            type      = tempType;
                            typeCache = XmlDeserializerCache.Get(type);
                        }
                    }
                }

                obj = Activator.CreateInstance(type);

                if (node.Attributes != null)
                {
                    foreach (XmlAttribute attribute in node.Attributes)
                    {
                        FieldInfo fieldInfo;
                        if (!typeCache.Fields.TryGetValue(attribute.Name, out fieldInfo))
                        {
                            continue;
                        }

                        fieldInfo.SetValue(obj, TransverseNode(fieldInfo.FieldType, attribute));
                    }
                }

                foreach (XmlNode childNode in node.ChildNodes)
                {
                    if (childNode.NodeType == XmlNodeType.Comment)
                    {
                        continue;
                    }

                    FieldInfo fieldInfo;
                    if (!typeCache.Fields.TryGetValue(childNode.Name, out fieldInfo))
                    {
                        continue;
                    }
                    var fieldType = fieldInfo.FieldType;

                    // 아이템을 각각 나열한 경우가 있어..
                    // 완전히 동일한 규칙의 재귀로 만들지 못함
                    if (fieldType.Name == "List`1")
                    {
                        continue;
                    }

                    fieldInfo.SetValue(obj, TransverseNode(fieldType, childNode));
                }

                if (listItemSeparated)
                {
                    foreach (var field in typeCache.Fields)
                    {
                        var fieldName = field.Key;
                        var fieldInfo = field.Value;
                        var fieldType = fieldInfo.FieldType;

                        if (fieldType.Name != "List`1")
                        {
                            continue;
                        }

                        var list = Activator.CreateInstance(fieldType);
                        fieldInfo.SetValue(obj, list);

                        var argType   = fieldType.GetGenericArguments()[0];
                        var addMethod = fieldType.GetMethod("Add");
                        var addArg    = new object[] { null };

                        foreach (XmlNode childNode in node.ChildNodes)
                        {
                            if (childNode.Name != fieldName)
                            {
                                continue;
                            }

                            addArg[0] = TransverseNode(argType, childNode);
                            addMethod.Invoke(list, addArg);
                        }
                    }
                }
            }

            return(obj);
        }
예제 #3
0
 public XmlDeserializer(Type type)
 {
     _type  = type;
     _cache = XmlDeserializerCache.Get(type);
 }