[Mono-list] Re: Remoting compatibility between MS.NET and Mono

Robert Jordan robertj@gmx.net
Tue, 01 Mar 2005 22:41:46 +0100


Hi Sébastien,

> I know for instance that basic types are compatibles between both platforms (array, string, int, etc.). Some classes (such as Guid)
> are also remotable, while other structs/classes such as CultureInfo and BitArray are not. Classes that share the same implementation
> on both sides are usually remotable (I never had problem with my own classes/structs).

Binary serialization depends on the *names* of the fields.
For example Mono uses for BitArray's implementation these
field names:

System.Collections.BitArray._array
System.Collections.BitArray._length
System.Collections.BitArray._version

while MSFT uses:

System.Collections.BitArray.m_array
System.Collections.BitArray.m_length
System.Collections.BitArray._version

It's quite hard for a Mono developer which is expected *not*
to cheat on MSFT's code to choose the same private field names.

It's even harder when a class is implementing ISerializable.
In this case the developer must cheat.

> On the other end, if there was a list of the compatible types available (on the mono web site for example), this could really help
> people like me to avoid using types that are not compatible (just a suggestion :-)

You may help yourself using the following code on both
platforms and diffing the output.

usage: mono sdump.exe PartialAssemblyName [TypeName]

samples:

mono sdump.exe mscorlib
mono sdump.exe mscorlib System.Collections.BitArray

bye
Rob

-- cut-here --
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;

public class SDumpApp
{
     [STAThread]
     static void Main(string[] args)
     {
         if (args == null || args.Length < 1)
         {
             Console.Error.WriteLine("usage: sdump PartialAssemblyName 
[TypeName]");
             Environment.Exit(1);
         }

         try
         {
             Assembly asm = Load(args[0]);
             if (args.Length > 1)
             {
                 Process(asm.GetType(args[1], true));
             }
             else
             {
                 Process(asm);
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine(ex.Message);
         }

     }

     static Assembly Load(string name)
     {
         Assembly asm = Assembly.LoadWithPartialName(name);
         if (asm == null)
         {
             throw new TypeLoadException(String.Format("Assembly '{0}' 
not found.", name));
         }
         else
         {
             return asm;
         }
     }

     static bool IsTypeApplicable(Type t)
     {
         if (t.IsSerializable && 
!typeof(ISerializable).IsAssignableFrom(t))
             return true;
         else
             return false;
     }

     static void Process(Assembly asm)
     {
         Type[] types = asm.GetExportedTypes();
         int count = 0;
         foreach (Type t in types)
         {
             if (IsTypeApplicable(t))
             {
                 Process(t);
                 count++;
             }
         }
         Console.WriteLine("#{0}", count);
     }

     static void Process(Type t)
     {
         foreach (MemberInfo mi in 
FormatterServices.GetSerializableMembers(t))
         {
             Console.WriteLine("{0}.{1}", t.FullName, mi.Name);
         }
     }

}