public void Serialize(XmlWriter xtw, object o, MappingActions mappingActions, List <object> nestedObjs)
        {
            if (nestedObjs.Contains(o))
            {
                throw new XmlRpcUnsupportedTypeException(nestedObjs[0].GetType(),
                                                         "Cannot serialize recursive data structure");
            }
            nestedObjs.Add(o);
            try
            {
                xtw.WriteStartElement("", "value", "");
                var xType = XmlRpcTypeInfo.GetXmlRpcType(o);
                switch (xType)
                {
                case XmlRpcType.tArray:
                    xtw.WriteStartElement("", "array", "");
                    xtw.WriteStartElement("", "data", "");
                    var a = (Array)o;
                    foreach (object aobj in a)
                    {
                        //if (aobj == null)
                        //  throw new XmlRpcMappingSerializeException(String.Format(
                        //    "Items in array cannot be null ({0}[]).",
                        //o.GetType().GetElementType()));
                        Serialize(xtw, aobj, mappingActions, nestedObjs);
                    }
                    WriteFullEndElement(xtw);
                    WriteFullEndElement(xtw);
                    break;

                case XmlRpcType.tMultiDimArray:
                    var mda     = (Array)o;
                    var indices = new int[mda.Rank];
                    BuildArrayXml(xtw, mda, 0, indices, mappingActions, nestedObjs);
                    break;

                case XmlRpcType.tBase64:
                    var buf = (byte[])o;
                    xtw.WriteStartElement("", "base64", "");
                    xtw.WriteBase64(buf, 0, buf.Length);
                    WriteFullEndElement(xtw);
                    break;

                case XmlRpcType.tBoolean:
                    var strBoolVal = (bool)o ? "1" : "0";
                    WriteFullElementString(xtw, "boolean", strBoolVal);
                    break;

                case XmlRpcType.tDateTime:
                    var dt  = (DateTime)o;
                    var sdt = dt.ToString("yyyyMMdd'T'HH':'mm':'ss",
                                          DateTimeFormatInfo.InvariantInfo);
                    WriteFullElementString(xtw, "dateTime.iso8601", sdt);
                    break;

                case XmlRpcType.tDouble:
                    double doubleVal = (double)o;
                    WriteFullElementString(xtw, "double", doubleVal.ToString(null,
                                                                             CultureInfo.InvariantCulture));
                    break;

                case XmlRpcType.tHashtable:
                    xtw.WriteStartElement("", "struct", "");
                    var xrs = o as XmlRpcStruct;
                    foreach (object obj in xrs.Keys)
                    {
                        string skey = obj as string;
                        xtw.WriteStartElement("", "member", "");
                        WriteFullElementString(xtw, "name", skey);
                        Serialize(xtw, xrs[skey], mappingActions, nestedObjs);
                        WriteFullEndElement(xtw);
                    }
                    WriteFullEndElement(xtw);
                    break;

                case XmlRpcType.tInt32:
                    o = SerializeInt32(xtw, o, mappingActions);
                    break;

                case XmlRpcType.tInt64:
                    o = SerializeInt64(xtw, o, mappingActions);
                    break;

                case XmlRpcType.tString:
                    SerializeString(xtw, o);
                    break;

                case XmlRpcType.tStruct:
                    MappingActions structActions = GetMappingActions(o.GetType(), mappingActions);
                    xtw.WriteStartElement("", "struct", "");
                    MemberInfo[] mis = o.GetType().GetMembers();
                    foreach (var mi in mis)
                    {
                        if (Attribute.IsDefined(mi, typeof(NonSerializedAttribute)))
                        {
                            continue;
                        }

                        if (mi.MemberType == MemberTypes.Field)
                        {
                            var fi      = (FieldInfo)mi;
                            var member  = fi.Name;
                            var attrchk = Attribute.GetCustomAttribute(fi, typeof(XmlRpcMemberAttribute));
                            if (attrchk != null && attrchk is XmlRpcMemberAttribute)
                            {
                                var mmbr = ((XmlRpcMemberAttribute)attrchk).Member;
                                if (mmbr != "")
                                {
                                    member = mmbr;
                                }
                            }
                            var memberActions = MemberMappingActions(o.GetType(), fi.Name, structActions);
                            if (fi.GetValue(o) == null)
                            {
                                if (memberActions.NullMappingAction == NullMappingAction.Ignore)
                                {
                                    continue;
                                }

                                if (memberActions.NullMappingAction == NullMappingAction.Error)
                                {
                                    throw new XmlRpcMappingSerializeException(@"Member """ + member +
                                                                              @""" of struct """ + o.GetType().Name + @""" cannot be null.");
                                }
                            }
                            xtw.WriteStartElement("", "member", "");
                            WriteFullElementString(xtw, "name", member);
                            Serialize(xtw, fi.GetValue(o), memberActions, nestedObjs);
                            WriteFullEndElement(xtw);
                        }
                        else if (mi.MemberType == MemberTypes.Property)
                        {
                            var pi      = (PropertyInfo)mi;
                            var member  = pi.Name;
                            var attrchk = Attribute.GetCustomAttribute(pi, typeof(XmlRpcMemberAttribute));
                            if (attrchk != null && attrchk is XmlRpcMemberAttribute)
                            {
                                var mmbr = ((XmlRpcMemberAttribute)attrchk).Member;
                                if (mmbr != "")
                                {
                                    member = mmbr;
                                }
                            }
                            var memberActions = MemberMappingActions(o.GetType(), pi.Name, structActions);
                            if (pi.GetValue(o, null) == null)
                            {
                                if (memberActions.NullMappingAction == NullMappingAction.Ignore)
                                {
                                    continue;
                                }

                                if (memberActions.NullMappingAction == NullMappingAction.Error)
                                {
                                    throw new XmlRpcMappingSerializeException(@"Member """ + member +
                                                                              @""" of struct """ + o.GetType().Name + @""" cannot be null.");
                                }
                            }
                            xtw.WriteStartElement("", "member", "");
                            WriteFullElementString(xtw, "name", member);
                            Serialize(xtw, pi.GetValue(o, null), memberActions, nestedObjs);
                            WriteFullEndElement(xtw);
                        }
                    }
                    WriteFullEndElement(xtw);
                    break;

                case XmlRpcType.tVoid:
                    WriteFullElementString(xtw, "string", "");
                    break;

                case XmlRpcType.tNil:
                    xtw.WriteStartElement("nil");
                    WriteFullEndElement(xtw);
                    break;

                default:
                    throw new XmlRpcUnsupportedTypeException(o.GetType());
                }

                WriteFullEndElement(xtw);
            }
            catch (NullReferenceException)
            {
                throw new XmlRpcNullReferenceException("Attempt to serialize data "
                                                       + "containing null reference");
            }
            finally
            {
                nestedObjs.RemoveAt(nestedObjs.Count - 1);
            }
        }
Esempio n. 2
0
        private object MapArray(IEnumerator <Node> iter, Type valType, MappingStack mappingStack, MappingAction mappingAction, out Type mappedType)
        {
            mappedType = null;
            // required type must be an array
            if (valType != null && !(valType.IsArray == true || valType == typeof(Array) || valType == typeof(object)))
            {
                throw new XmlRpcTypeMismatchException(mappingStack.MappingType
                                                      + $" contains array value where{XmlRpcTypeInfo.GetXmlRpcTypeString(valType)}"
                                                      + $" expected {StackDump(mappingStack)}");
            }

            if (valType != null)
            {
                XmlRpcType xmlRpcType = XmlRpcTypeInfo.GetXmlRpcType(valType);
                if (xmlRpcType == XmlRpcType.tMultiDimArray)
                {
                    mappingStack.Push("array mapped to type " + valType.Name);
                    return(MapMultiDimArray(iter, valType, mappingStack, mappingAction));
                }
                mappingStack.Push("array mapped to type " + valType.Name);
            }
            else
            {
                mappingStack.Push("array");
            }

            var values   = new List <object>();
            var elemType = DetermineArrayItemType(valType);

            while (iter.MoveNext() && iter.Current is ValueNode)
            {
                mappingStack.Push(string.Format("element {0}", values.Count));
                var value = MapValueNode(iter, elemType, mappingStack, mappingAction);
                values.Add(value);
                mappingStack.Pop();
            }

            var  bGotType = false;
            Type useType  = null;

            foreach (object value in values)
            {
                if (value == null)
                {
                    continue;
                }

                if (bGotType)
                {
                    if (useType != value.GetType())
                    {
                        useType = null;
                    }

                    continue;
                }

                useType  = value.GetType();
                bGotType = true;
            }

            var args = new object[1];

            args[0] = values.Count;
            object retObj = null;

            if (valType != null && valType != typeof(Array) && valType != typeof(object))
            {
                retObj = CreateArrayInstance(valType, args);
            }
            else
            {
                if (useType == null)
                {
                    retObj = CreateArrayInstance(typeof(object[]), args);
                }
                else
                {
                    retObj = Array.CreateInstance(useType, (int)args[0]);
                }
            }

            for (int j = 0; j < values.Count; j++)
            {
                ((Array)retObj).SetValue(values[j], j);
            }

            mappingStack.Pop();

            return(retObj);
        }