[Mono-devel-list] Patch to mimic MS.Net remoting name mangling

Luke Ravitch ravitch at nrtc.northrop.com
Mon May 2 15:17:06 EDT 2005


I put together a little patch to improve Mono-MS.Net remoting
compatibility.  Basically, MS.Net mangles the names of private
inherited fields for SOAP-serialized objects.  I've opened a bug
(#74760) to track the issue...

    http://bugs.ximian.com/show_bug.cgi?id=74760

Please see it for a more detailed description of the issue.

Attached here is the patch (also with the bug report).  Does it look
reasonable?

Because it looked like it belongs in the same place, I also added
support for the SoapFieldAttribute.XmlFieldName in the serializer.
(The attribute was implemented, but the SOAP serialization stuff
didn't use it.)  Of course, that's still only a very partial
implementation of the SoapFieldAttribute stuff.

I wasn't sure where to put the name mangling routine because both
SoapReader and SoapWriter need to use it.  So I just picked one and
went with it.

-- 
Luke Ravitch  <ravitch at nrtc.northrop.com>   Telephone: 310-864-7478
Software Engr., Advanced Software Sys. | One Hornet Way, MS 9M52/W6
Northrop  Grumman  Integrated  Systems | El Segundo, CA 90245-23804
-------------- next part --------------
Index: mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapWriter.cs
===================================================================
--- mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapWriter.cs	(revision 43735)
+++ mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapWriter.cs	(working copy)
@@ -391,6 +391,8 @@
 //					bool specifyEncoding = false;
 //					if(objectData[i] != null)
 //						 specifyEncoding = (objectData[i].GetType() != fieldInfo.FieldType);
+
+					string name = SoapReader.GetFieldName (fieldInfo, currentType);
 					_xmlWriter.WriteStartElement(fieldInfo.Name);
 					SerializeComponent(
 						objectData[i], 
Index: mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapReader.cs
===================================================================
--- mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapReader.cs	(revision 43735)
+++ mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapReader.cs	(working copy)
@@ -729,7 +729,39 @@
 					indices);
 			}
 		}
-
+
+		// MS.Net uses "_x002B_" in serialization to delimit base class from field name for
+		// private inherited fields (see GetFieldName below).  Any instances of "_x002B_"
+		// in the original field name are escaped with "_x005F_", as are any prior instances
+		// of "_x005F_".  This function performs that escaping.
+		
+		static private string EscapeName (string s)
+		{
+			return (s.Replace ("_x005F_", "_x005F_x005F_")).Replace ("_x002B_", "_x005F_x002B_");
+		}
+
+		static public string GetFieldName (FieldInfo info, Type type)
+		{
+			string name;
+			Type attr_t = typeof (SoapFieldAttribute);
+			SoapFieldAttribute soapAttr = Attribute.GetCustomAttribute (info, attr_t) as SoapFieldAttribute;
+
+			if ((soapAttr != null) && (soapAttr.XmlElementName != null)) {
+				name = EscapeName (soapAttr.XmlElementName);
+			} else {
+				name = EscapeName (info.Name);
+				// To maintain compatibility with MS.Net, we need to mangle the names
+				// of any private inherited members that don't have XmlElementName set
+				// in a SoapFieldAttribute.  MS.Net prepends the base class name to
+				// the field name, using "_x002B_" as a delimiter.
+				if (info.IsPrivate && (info.DeclaringType != type)) {
+					name = EscapeName (info.DeclaringType.Name) + "_x002B_" + name;
+				}
+			}
+
+			return name;
+		}
+		
 		TypeMetadata GetTypeMetadata (Type type)
 		{
 			TypeMetadata tm = _fieldIndices[type] as TypeMetadata;
@@ -738,10 +770,14 @@
 			tm = new TypeMetadata ();
 			tm.MemberInfos = FormatterServices.GetSerializableMembers (type, _context);
 			
-			tm.Indices	= new Hashtable();
-			for(int i = 0; i < tm.MemberInfos.Length; i++) 
-				tm.Indices.Add (tm.MemberInfos[i].Name, i);
-			
+			tm.Indices = new Hashtable();
+			for (int i = 0; i < tm.MemberInfos.Length; i++) {
+				// Only fields should be serializable, so this should never be null.
+				FieldInfo fieldInfo = tm.MemberInfos[i] as FieldInfo;
+
+				tm.Indices.Add (GetFieldName (fieldInfo, type), i);
+			} 
+
 			_fieldIndices[type] = tm;
 			return tm;
 		}


More information about the Mono-devel-list mailing list