[Web.Services] Add support for optional parameters
authorLluis Sanchez <lluis@novell.com>
Thu, 28 Apr 2011 16:28:11 +0000 (18:28 +0200)
committerLluis Sanchez <lluis@novell.com>
Thu, 28 Apr 2011 16:33:59 +0000 (18:33 +0200)
Non-nullable web service parameters can be made optional by
adding an additional parameter with the same name and a
'Specified' suffix. This was supported when serializing
classes, but not when serializing web service parameters.
This might fix bug 688496.

mcs/class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs
mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs

index 4d9f3f3d3539d61bc7ba54492a99b85e4ee963bf..ac5401d851f23871571a71508295c7da7de972b9 100644 (file)
@@ -1228,7 +1228,10 @@ namespace System.Xml.Serialization
                string GenerateMemberHasValueCondition (XmlTypeMapMember member, string ob, bool isValueList)
                {
                        if (isValueList) {
-                               return ob + ".Length > " + member.GlobalIndex;
+                               if (member.IsOptionalValueType)
+                                       return ob + ".Length > " + Math.Max (member.GlobalIndex, member.SpecifiedGlobalIndex) + " && " + GetCast (typeof(bool), ob + "[" + member.SpecifiedGlobalIndex + "]");
+                               else
+                                       return ob + ".Length > " + member.GlobalIndex;
                        }
                        else if (member.DefaultValue != System.DBNull.Value) {
                                string mem = ob + ".@" + member.Name;
@@ -2106,11 +2109,24 @@ namespace System.Xml.Serialization
 
                void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList)
                {
-                       if (isValueList) WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
+                       GenerateSetMemberValue (member, ob, value, isValueList, false);
+               }
+               
+               void GenerateSetMemberValue (XmlTypeMapMember member, string ob, string value, bool isValueList, bool initializingMember)
+               {
+                       if (isValueList) {
+                               WriteLine (ob + "[" + member.GlobalIndex + "] = " + value + ";");
+                               if (member.IsOptionalValueType) {
+                                       string val = initializingMember ? "false" : "true";
+                                       WriteLine (ob + "[" + member.SpecifiedGlobalIndex + "] = " + val + ";");
+                               }
+                       }
                        else {
                                WriteLine (ob + ".@" + member.Name + " = " + value + ";");
-                               if (member.IsOptionalValueType)
-                                       WriteLine (ob + "." + member.Name + "Specified = true;");
+                               if (member.IsOptionalValueType) {
+                                       string val = initializingMember ? "false" : "true";
+                                       WriteLine (ob + "." + member.Name + "Specified = " + val + ";");
+                               }
                        }
                }
 
@@ -2122,7 +2138,7 @@ namespace System.Xml.Serialization
                        
                        if (member.TypeData.Type.IsEnum)
                                value = GetCast (member.TypeData.Type, value);
-                       GenerateSetMemberValue (member, ob, value, isValueList);
+                       GenerateSetMemberValue (member, ob, value, isValueList, true);
                }
 
                string GenerateReadObjectElement (XmlTypeMapElementInfo elem)
index 34a241d772a435eb8fc08986442644a0bc2b8c61..ad3223c3bf470fad463c1cc857f2b0ca5c9904e2 100644 (file)
@@ -150,14 +150,17 @@ namespace System.Xml.Serialization {
                {
 //                     Reset ();       Disabled. See ChangeLog
 
-                       XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
+                       ArrayList mapping = new ArrayList ();
                        for (int n=0; n<members.Length; n++)
                        {
+                               if (members[n].XmlAttributes.XmlIgnore) continue;
                                XmlTypeMapMember mapMem = CreateMapMember (null, members[n], ns);
-                               mapping[n] = new XmlMemberMapping (members[n].MemberName, ns, mapMem, false);
+                               mapMem.GlobalIndex = n;
+                               mapMem.CheckOptionalValueType (members);
+                               mapping.Add (new XmlMemberMapping (members[n].MemberName, ns, mapMem, false));
                        }
                        elementName = XmlConvert.EncodeLocalName (elementName);
-                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, mapping);
+                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, false, (XmlMemberMapping[])mapping.ToArray (typeof(XmlMemberMapping)));
                        mps.RelatedMaps = relatedMaps;
                        mps.Format = SerializationFormat.Literal;
                        Type[] extraTypes = includedTypes != null ? (Type[])includedTypes.ToArray(typeof(Type)) : null;
index 4a44f934f0e628f90707e089691dfe7b950d4eaf..ab6a2785304199533718852f61b6c32e22df6e1e 100644 (file)
@@ -583,12 +583,12 @@ namespace System.Xml.Serialization
 
                void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList)
                {
-                       if (isValueList) ((object[])ob)[member.GlobalIndex] = value;
-                       else {
+                       if (isValueList)
+                               ((object[])ob)[member.GlobalIndex] = value;
+                       else
                                member.SetValue (ob, value);
-                               if (member.IsOptionalValueType)
-                                       member.SetValueSpecified (ob, true); 
-                       }
+                       if (member.IsOptionalValueType)
+                               member.SetValueSpecified (ob, true); 
                }
 
                void SetMemberValueFromAttr (XmlTypeMapMember member, object ob, object value, bool isValueList)
index e870f4093a53611407b4c445042015869d5dcee3..49c7796677b6dec5a691e398999a55ac11b32d17 100644 (file)
@@ -285,6 +285,8 @@ namespace System.Xml.Serialization
                bool MemberHasValue (XmlTypeMapMember member, object ob, bool isValueList)
                {
                        if (isValueList) {
+                               if (member.IsOptionalValueType && !member.GetValueSpecified (ob))
+                                       return false;
                                return member.GlobalIndex < ((object[])ob).Length;
                        }
                        else if (member.DefaultValue != System.DBNull.Value) {
index e3cd8bc869527412a3895d87b2e28e934227106c..9d2b846d4370bf5a62e3f29e650f12044d2006e0 100644 (file)
@@ -42,6 +42,7 @@ namespace System.Xml.Serialization
                string _name;
                int _index;
                int _globalIndex;
+               int _specifiedGlobalIndex = -1;
                TypeData _typeData;
                MemberInfo _member;
                MemberInfo _specifiedMember;
@@ -138,6 +139,11 @@ namespace System.Xml.Serialization
                        set { _globalIndex = value; }
                }
                
+               public int SpecifiedGlobalIndex
+               {
+                       get { return _specifiedGlobalIndex; }
+               }
+               
                public bool IsOptionalValueType
                {
                        get { return (_flags & OPTIONAL) != 0; }
@@ -158,20 +164,44 @@ namespace System.Xml.Serialization
                
                public void CheckOptionalValueType (Type type)
                {
+                       // Used when reflecting a type
                        if (_member == null) InitMember (type);
                        IsOptionalValueType = (_specifiedMember != null);
                }
                
+               public void CheckOptionalValueType (XmlReflectionMember[] members)
+               {
+                       // Used when reflecting a list of members (e.g. web service parameters)
+                       for (int n=0; n<members.Length; n++) {
+                               XmlReflectionMember m = members [n];
+                               if (m.MemberName == Name + "Specified" && m.MemberType == typeof(bool) && m.XmlAttributes.XmlIgnore) {
+                                       IsOptionalValueType = true;
+                                       _specifiedGlobalIndex = n;
+                                       break;
+                               }
+                       }
+               }
+               
                public bool GetValueSpecified (object ob)
                {
-                       if (_specifiedMember is PropertyInfo) return (bool) ((PropertyInfo)_specifiedMember).GetValue (ob, null);
-                       else return (bool) ((FieldInfo)_specifiedMember).GetValue (ob);
+                       if (_specifiedGlobalIndex != -1) {
+                               object[] array = (object[])ob;
+                               return _specifiedGlobalIndex < array.Length && (bool) array [_specifiedGlobalIndex];
+                       }
+                       else if (_specifiedMember is PropertyInfo)
+                               return (bool) ((PropertyInfo)_specifiedMember).GetValue (ob, null);
+                       else
+                               return (bool) ((FieldInfo)_specifiedMember).GetValue (ob);
                }
 
                public void SetValueSpecified (object ob, bool value)
                {
-                       if (_specifiedMember is PropertyInfo) ((PropertyInfo)_specifiedMember).SetValue (ob, value, null);
-                       else ((FieldInfo)_specifiedMember).SetValue (ob, value);
+                       if (_specifiedGlobalIndex != -1)
+                               ((object[])ob) [_specifiedGlobalIndex] = value;
+                       else if (_specifiedMember is PropertyInfo)
+                               ((PropertyInfo)_specifiedMember).SetValue (ob, value, null);
+                       else
+                               ((FieldInfo)_specifiedMember).SetValue (ob, value);
                }
                
                public virtual bool RequiresNullable {
index d8ef203e13cfd590861e01d34d90ce57d7569ddb..fbef2b3d6819b080d9ac79abc471ac481b06f0db 100644 (file)
@@ -305,7 +305,6 @@ namespace System.Xml.Serialization
 
                public void AddMember (XmlTypeMapMember member)
                {
-                       member.GlobalIndex = _allMembers.Count;
                        _allMembers.Add (member);
                        
                        if (!(member.DefaultValue is System.DBNull) && member.DefaultValue != null) {