CookComputing.XmlRpc.XmlRpcSerializer.ParseStruct C# (CSharp) Method

ParseStruct() private method

private ParseStruct ( XmlNode node, Type valueType, ParseStack parseStack, MappingAction mappingAction ) : Object
node System.Xml.XmlNode
valueType System.Type
parseStack ParseStack
mappingAction MappingAction
return Object
        Object ParseStruct(
            XmlNode node,
            Type valueType,
            ParseStack parseStack,
            MappingAction mappingAction)
        {
            if (valueType.IsPrimitive || valueType.IsArray)
              {
            throw new XmlRpcTypeMismatchException(parseStack.ParseType
              + " contains struct value where "
              + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType)
              + " expected (as type " + valueType.Name + ") "
              + StackDump(parseStack));
              }
            #if !FX1_0
              if (valueType.IsGenericType
            && valueType.GetGenericTypeDefinition() == typeof(Nullable<>))
              {
            valueType = valueType.GetGenericArguments()[0];
              }
            #endif
              object retObj;
              try
              {
            retObj = Activator.CreateInstance(valueType);
              }
              catch (Exception ex)
              {
            throw new XmlRpcTypeMismatchException(parseStack.ParseType
              + " contains struct value where "
              + XmlRpcServiceInfo.GetXmlRpcTypeString(valueType)
              + " expected (unable to create instance of " + valueType.Name
              + ", possibly no default constructor) "
              + StackDump(parseStack));
              }
              // Note: mapping action on a struct is only applied locally - it
              // does not override the global mapping action when members of the
              // struct are parsed
              MappingAction localAction = mappingAction;
              if (valueType != null)
              {
            parseStack.Push("struct mapped to type " + valueType.Name);
            localAction = StructMappingAction(valueType, mappingAction);
              }
              else
              {
            parseStack.Push("struct");
              }
              // create map of field names and remove each name from it as
              // processed so we can determine which fields are missing
              // TODO: replace HashTable with lighter collection
              Hashtable names = new Hashtable();
              foreach (FieldInfo fi in valueType.GetFields())
              {
            names.Add(fi.Name, fi.Name);
              }
              foreach (PropertyInfo pi in valueType.GetProperties())
              {
            names.Add(pi.Name, pi.Name);
              }
              XmlNodeList members = node.ChildNodes;
              int fieldCount = 0;
              foreach (XmlNode member in members)
              {
            if (member.Name != "member")
              continue;
            XmlNode nameNode;
            bool dupName;
            XmlNode valueNode;
            bool dupValue;
            SelectTwoNodes(member, "name", out nameNode, out dupName, "value",
              out valueNode, out dupValue);
            if (nameNode == null)
              throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType
            + " contains a member with missing name element"
            + " " + StackDump(parseStack));
            if (dupName)
              throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType
            + " contains member with more than one name element"
            + " " + StackDump(parseStack));
            string name = nameNode.FirstChild.Value;
            if (valueNode == null)
              throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType
            + " contains struct member " + name + " with missing value "
            + " " + StackDump(parseStack));
            if (dupValue)
              throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType
            + " contains member with more than one value element"
            + " " + StackDump(parseStack));
            string structName = GetStructName(valueType, name);
            if (structName != null)
              name = structName;
            if (names.Contains(name))
              names.Remove(name);
            else
            {
              if (!IgnoreDuplicateMembers
              && (valueType.GetField(name) != null || valueType.GetProperty(name) != null))
            throw new XmlRpcInvalidXmlRpcException(parseStack.ParseType
              + " contains struct value with duplicate member "
              + nameNode.FirstChild.Value
              + " " + StackDump(parseStack));
              else
            continue;   // ignore duplicate member
            }
            MemberInfo[] mis = valueType.GetMember(name);
            if (mis.Length == 0)
            {
              continue;   // allow unexpected members
            }
            Object valObj = null;
            switch (mis[0].MemberType)
            {
              case MemberTypes.Field:
            FieldInfo fi = (FieldInfo)mis[0];
            if (valueType == null)
              parseStack.Push(String.Format("member {0}", name));
            else
              parseStack.Push(String.Format("member {0} mapped to type {1}",
                name,fi.FieldType.Name));
            try
            {
              valObj = ParseValue(valueNode.FirstChild, fi.FieldType,
                parseStack, mappingAction);
            }
            catch(XmlRpcInvalidXmlRpcException)
            {
              if (valueType != null && localAction == MappingAction.Error)
              {
                MappingAction memberAction = MemberMappingAction(valueType,
                  name, MappingAction.Error);
                if (memberAction == MappingAction.Error)
                  throw;
              }
            }
            finally
            {
              parseStack.Pop();
            }
            fi.SetValue(retObj, valObj);
            break ;
              case MemberTypes.Property :
            PropertyInfo pi = (PropertyInfo)mis[0] ;
            if (valueType == null)
              parseStack.Push(String.Format("member {0}", name));
            else

              parseStack.Push(String.Format("member {0} mapped to type {1}",
                name,pi.PropertyType.Name));
            valObj = ParseValue(valueNode.FirstChild, pi.PropertyType,
              parseStack, mappingAction);
            parseStack.Pop();

            pi.SetValue(retObj, valObj, null);
            break ;
            }
            fieldCount++;
              }
              if (localAction == MappingAction.Error && names.Count > 0)
            ReportMissingMembers(valueType, names, parseStack);
              parseStack.Pop();
              return retObj;
        }