Merge pull request #615 from nealef/master
authorMiguel de Icaza <miguel@gnome.org>
Fri, 26 Apr 2013 16:55:22 +0000 (09:55 -0700)
committerMiguel de Icaza <miguel@gnome.org>
Fri, 26 Apr 2013 16:55:22 +0000 (09:55 -0700)
Fix incompatibility with .NET's serialization of ObservableCollection

mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs
mcs/class/WindowsBase/System.Collections.ObjectModel/ObservableCollection.cs
mcs/class/corlib/System.Collections.ObjectModel/Collection.cs
mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs
mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs

index 6c26e8795f62cf037c1eddafeec9a8dd8ce73aa3..32926907e2167c199c04d9c7d7d332221e4e31d2 100644 (file)
@@ -40,30 +40,33 @@ namespace System.Collections.ObjectModel
 #endif
        public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged {
                [Serializable]
-               sealed class Reentrant : IDisposable {
-                       private int count = 0;
+#if !MOBILE
+       [TypeForwardedFrom (Consts.WindowsBase_3_0)]
+#endif
+               sealed class SimpleMonitor : IDisposable {
+                       private int _busyCount = 0;
 
-                       public Reentrant()
+                       public SimpleMonitor()
                        {
                        }
 
                        public void Enter()
                        {
-                               count++;
+                               _busyCount++;
                        }
 
                        public void Dispose()
                        {
-                               count--;
+                               _busyCount--;
                        }
 
                        public bool Busy
                        {
-                               get { return count > 0; }
+                               get { return _busyCount > 0; }
                        }
                }
 
-               private Reentrant reentrant = new Reentrant ();
+               private SimpleMonitor _monitor = new SimpleMonitor ();
 
                public ObservableCollection ()
                {
@@ -83,7 +86,9 @@ namespace System.Collections.ObjectModel
                {
                }
 
+               [field:NonSerializedAttribute()]
                public virtual event NotifyCollectionChangedEventHandler CollectionChanged;
+               [field:NonSerializedAttribute()]
                protected virtual event PropertyChangedEventHandler PropertyChanged;
 
                event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
@@ -93,8 +98,8 @@ namespace System.Collections.ObjectModel
 
                protected IDisposable BlockReentrancy ()
                {
-                       reentrant.Enter ();
-                       return reentrant;
+                       _monitor.Enter ();
+                       return _monitor;
                }
 
                protected void CheckReentrancy ()
@@ -102,7 +107,7 @@ namespace System.Collections.ObjectModel
                        NotifyCollectionChangedEventHandler eh = CollectionChanged;
 
                        // Only have a problem if we have more than one event listener.
-                       if (reentrant.Busy && eh != null && eh.GetInvocationList ().Length > 1)
+                       if (_monitor.Busy && eh != null && eh.GetInvocationList ().Length > 1)
                                throw new InvalidOperationException ("Cannot modify the collection while reentrancy is blocked.");
                }
 
index 1ea166cd9ac3134a1165f5513852e53a8112fb9d..bcc4440e109d423770f5977678b1e59dad6e8187 100644 (file)
@@ -44,7 +44,7 @@ namespace System.Collections.ObjectModel
        public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged {
                
                private class Reentrant : IDisposable {
-                       private int count = 0;
+                       private int _busyCount = 0;
 
                        public Reentrant()
                        {
@@ -52,17 +52,17 @@ namespace System.Collections.ObjectModel
 
                        public void Enter()
                        {
-                               count++;
+                               _busyCount++;
                        }
 
                        public void Dispose()
                        {
-                               count--;
+                               _busyCount--;
                        }
 
                        public bool Busy
                        {
-                               get { return count > 0; }
+                               get { return _busyCount > 0; }
                        }
                }
 
index 6a57a75acbacf7d894cf042626ab2f46a1c777ca..b9d6a3e71e4adf165a435913d9c289cacecc9e70 100644 (file)
@@ -53,8 +53,7 @@ namespace System.Collections.ObjectModel
                , IReadOnlyList<T>
 #endif
        {
-               IList <T> items;
-               [field:NonSerializedAttribute()]
+               IList <T> list;
                object syncRoot;
                
                public Collection ()
@@ -62,21 +61,21 @@ namespace System.Collections.ObjectModel
                        List <T> l = new List <T> ();
                        IList l2 = l as IList;
                        syncRoot = l2.SyncRoot;
-                       items = l;
+                       list = l;
                }
 
-               public Collection (IList <T> items)
+               public Collection (IList <T> list)
                {
-                       if (items == null)
-                               throw new ArgumentNullException ("items");
-                       this.items = items;
-                       ICollection l = items as ICollection;
+                       if (list == null)
+                               throw new ArgumentNullException ("list");
+                       this.list = list;
+                       ICollection l = list as ICollection;
                        syncRoot = (l != null) ? l.SyncRoot : new object ();
                }
 
                public void Add (T item)
                {
-                       int idx = items.Count;
+                       int idx = list.Count;
                        InsertItem (idx, item);
                }
 
@@ -87,27 +86,27 @@ namespace System.Collections.ObjectModel
 
                protected virtual void ClearItems ()
                {
-                       items.Clear ();
+                       list.Clear ();
                }
 
                public bool Contains (T item)
                {
-                       return items.Contains (item);
+                       return list.Contains (item);
                }
 
                public void CopyTo (T [] array, int index)
                {
-                       items.CopyTo (array, index);
+                       list.CopyTo (array, index);
                }
 
                public IEnumerator <T> GetEnumerator ()
                {
-                       return items.GetEnumerator ();
+                       return list.GetEnumerator ();
                }
 
                public int IndexOf (T item)
                {
-                       return items.IndexOf (item);
+                       return list.IndexOf (item);
                }
 
                public void Insert (int index, T item)
@@ -117,11 +116,11 @@ namespace System.Collections.ObjectModel
 
                protected virtual void InsertItem (int index, T item)
                {
-                       items.Insert (index, item);
+                       list.Insert (index, item);
                }
 
                protected IList<T> Items {
-                       get { return items; }
+                       get { return list; }
                }
 
                public bool Remove (T item)
@@ -142,25 +141,25 @@ namespace System.Collections.ObjectModel
 
                protected virtual void RemoveItem (int index)
                {
-                       items.RemoveAt (index);
+                       list.RemoveAt (index);
                }
 
                public int Count {
-                       get { return items.Count; }
+                       get { return list.Count; }
                }
 
                public T this [int index] {
-                       get { return items [index]; }
+                       get { return list [index]; }
                        set { SetItem (index, value); }
                }
 
                bool ICollection<T>.IsReadOnly {
-                       get { return items.IsReadOnly; }
+                       get { return list.IsReadOnly; }
                }
 
                protected virtual void SetItem (int index, T item)
                {
-                       items[index] = item;
+                       list[index] = item;
                }
 
                
@@ -173,21 +172,21 @@ namespace System.Collections.ObjectModel
                        throw new ArgumentException ("item");
                }
                
-               internal static void CheckWritable (IList <T> items)
+               internal static void CheckWritable (IList <T> list)
                {
-                       if (items.IsReadOnly)
+                       if (list.IsReadOnly)
                                throw new NotSupportedException ();
                }
                
-               internal static bool IsSynchronized (IList <T> items)
+               internal static bool IsSynchronized (IList <T> list)
                {
-                       ICollection c = items as ICollection;
+                       ICollection c = list as ICollection;
                        return (c != null) ? c.IsSynchronized : false;
                }
                
-               internal static bool IsFixedSize (IList <T> items)
+               internal static bool IsFixedSize (IList <T> list)
                {
-                       IList l = items as IList;
+                       IList l = list as IList;
                        return (l != null) ? l.IsFixedSize : false;
                }
 #endregion
@@ -195,17 +194,17 @@ namespace System.Collections.ObjectModel
 #region Not generic interface implementations
                void ICollection.CopyTo (Array array, int index)
                {
-                       ((ICollection)items).CopyTo (array, index);
+                       ((ICollection)list).CopyTo (array, index);
                }
                
                IEnumerator IEnumerable.GetEnumerator ()
                {
-                       return (IEnumerator) items.GetEnumerator ();
+                       return (IEnumerator) list.GetEnumerator ();
                }
                                
                int IList.Add (object value)
                {
-                       int idx = items.Count;
+                       int idx = list.Count;
                        InsertItem (idx, ConvertItem (value));
                        return idx;
                }
@@ -213,14 +212,14 @@ namespace System.Collections.ObjectModel
                bool IList.Contains (object value)
                {
                        if (CollectionHelpers.IsValidItem<T> (value))
-                               return items.Contains ((T) value);
+                               return list.Contains ((T) value);
                        return false;
                }
                
                int IList.IndexOf (object value)
                {
                        if (CollectionHelpers.IsValidItem<T> (value))
-                               return items.IndexOf ((T) value);
+                               return list.IndexOf ((T) value);
                        return -1;
                }
                
@@ -231,7 +230,7 @@ namespace System.Collections.ObjectModel
                
                void IList.Remove (object value)
                {
-                       CheckWritable (items);
+                       CheckWritable (list);
 
                        int idx = IndexOf (ConvertItem (value));
 
@@ -239,22 +238,22 @@ namespace System.Collections.ObjectModel
                }
                
                bool ICollection.IsSynchronized {
-                       get { return IsSynchronized (items); }
+                       get { return IsSynchronized (list); }
                }
                
                object ICollection.SyncRoot {
                        get { return syncRoot; }
                }
                bool IList.IsFixedSize {
-                       get { return IsFixedSize (items); }
+                       get { return IsFixedSize (list); }
                }
                
                bool IList.IsReadOnly {
-                       get { return items.IsReadOnly; }
+                       get { return list.IsReadOnly; }
                }
                
                object IList.this [int index] {
-                       get { return items [index]; }
+                       get { return list [index]; }
                        set { SetItem (index, ConvertItem (value)); }
                }
 #endregion
index fd38471644b2d7ec9f2e23c0e5273b920ceb9dac..671c196163e08ad69c39a05bf664164bfdbc25ac 100644 (file)
@@ -115,8 +115,13 @@ namespace System.Runtime.Serialization.Formatters.Binary
                                        // EMIT ow.WriteAssembly (writer, memberType.Assembly);
                                        gen.Emit (OpCodes.Ldarg_1);
                                        gen.Emit (OpCodes.Ldarg_2);
+#if NET_4_0
+                                       EmitLoadType (gen, memberType);
+                                       gen.EmitCall (OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("WriteTypeAssembly"), null);
+#else
                                        EmitLoadTypeAssembly (gen, memberType, field.Name);
                                        gen.EmitCall (OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("WriteAssembly"), null);
+#endif
                                        gen.Emit (OpCodes.Pop);
                                }
                        }
@@ -292,8 +297,14 @@ namespace System.Runtime.Serialization.Formatters.Binary
                                        // EMIT writer.Write ((int)ow.GetAssemblyId (type.Assembly));
                                        gen.Emit (OpCodes.Ldarg_2);
                                        gen.Emit (OpCodes.Ldarg_1);
+#if NET_4_0
+                                       EmitLoadType (gen, type);
+                                       gen.EmitCall (OpCodes.Callvirt, typeof(GetForwardedAttribute).GetMethod("GetAssemblyName"), null);
+                                       gen.EmitCall (OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("GetAssemblyNameId"), null);
+#else
                                        EmitLoadTypeAssembly (gen, type, member);
                                        gen.EmitCall (OpCodes.Callvirt, typeof(ObjectWriter).GetMethod("GetAssemblyId"), null);
+#endif
                                        gen.Emit (OpCodes.Conv_I4);
                                        EmitWrite (gen, typeof(int));
                                        break;
@@ -318,6 +329,12 @@ namespace System.Runtime.Serialization.Formatters.Binary
                        gen.EmitCall (OpCodes.Callvirt, typeof(Type).GetProperty("Assembly").GetGetMethod(), null);
                }
                
+               static void EmitLoadType (ILGenerator gen, Type type)
+               {
+                       gen.Emit (OpCodes.Ldtoken, type);
+                       gen.EmitCall (OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null);
+               }
+               
                static void EmitWrite (ILGenerator gen, Type type)
                {
                        gen.EmitCall (OpCodes.Callvirt, typeof(BinaryWriter).GetMethod("Write", new Type[] { type }), null);
index 9d3c42bbd19d6e3c85134a0c2639f20adc501bcc..c5bf658a1c8ece4466957625fd9eb24df61bbc42 100644 (file)
@@ -35,9 +35,25 @@ using System.Runtime.Serialization;
 using System.Runtime.Remoting.Messaging;
 using System.Reflection;
 using System.Globalization;
+using System.Runtime.CompilerServices;
 
 namespace System.Runtime.Serialization.Formatters.Binary
 {
+#if NET_4_0
+       public class GetForwardedAttribute
+       {
+               public static string GetAssemblyName (Type self) 
+               {
+                       var attrs = self.GetCustomAttributes(
+                                       typeof (TypeForwardedFromAttribute), false);
+                       if (attrs.Length == 0)
+                               return self.Assembly.FullName;
+                       else
+                               return ((TypeForwardedFromAttribute)attrs [0]).AssemblyFullName;
+               }
+       }
+#endif
+
        abstract class TypeMetadata
        {
                public string TypeAssemblyName;
@@ -73,7 +89,11 @@ namespace System.Runtime.Serialization.Formatters.Binary
                {
                        InstanceType = instanceType;
                        InstanceTypeName = instanceType.FullName;
+#if NET_4_0
+                       TypeAssemblyName = GetForwardedAttribute.GetAssemblyName(instanceType);
+#else
                        TypeAssemblyName = instanceType.Assembly.FullName;
+#endif
                }
                
                public override bool RequiresTypes {
@@ -102,7 +122,11 @@ namespace System.Runtime.Serialization.Formatters.Binary
                        }
 
                        TypeAssemblyName = info.AssemblyName;
+#if NET_4_0
+                       InstanceTypeName = GetForwardedAttribute.GetAssemblyName(itype);
+#else
                        InstanceTypeName = info.FullTypeName;
+#endif
                }
                
                public override bool IsCompatible (TypeMetadata other)
@@ -129,7 +153,7 @@ namespace System.Runtime.Serialization.Formatters.Binary
                                while (type.IsArray) 
                                        type = type.GetElementType();
                                        
-                               ow.WriteAssembly (writer, type.Assembly);
+                               ow.WriteTypeAssembly (writer, type);
                        }
                }
                
@@ -142,7 +166,7 @@ namespace System.Runtime.Serialization.Formatters.Binary
                                writer.Write (name);
 
                        // Types of fields
-                       foreach (Type type in types)
+                       foreach (Type type in types) 
                                ObjectWriter.WriteTypeCode (writer, type);
 
                        // Type specs of fields
@@ -181,7 +205,7 @@ namespace System.Runtime.Serialization.Formatters.Binary
                                while (type.IsArray) 
                                        type = type.GetElementType();
                                        
-                               ow.WriteAssembly (writer, type.Assembly);
+                               ow.WriteTypeAssembly (writer, type);
                        }
                }
                
@@ -511,7 +535,7 @@ namespace System.Runtime.Serialization.Formatters.Binary
 
                        var tag = GetTypeTag (elementType);
                        if ((tag != TypeTag.ArrayOfObject) && (tag != TypeTag.ArrayOfString) && (tag != TypeTag.ArrayOfPrimitiveType))
-                               WriteAssembly (writer, elementType.Assembly);
+                               WriteTypeAssembly (writer, elementType);
 
                        // Writes the array
 
@@ -809,6 +833,15 @@ namespace System.Runtime.Serialization.Formatters.Binary
                        writer.Write (str);
                }
 
+               public int WriteTypeAssembly (BinaryWriter writer, Type aType)
+               {
+#if NET_4_0
+                       return WriteAssemblyName (writer, GetForwardedAttribute.GetAssemblyName(aType));
+#else
+                       return WriteAssemblyName (writer, aType.Assembly.FullName);
+#endif
+               }
+               
                public int WriteAssembly (BinaryWriter writer, Assembly assembly)
                {
                        return WriteAssemblyName (writer, assembly.FullName);
@@ -994,7 +1027,12 @@ namespace System.Runtime.Serialization.Formatters.Binary
 
                                case TypeTag.GenericType:
                                        writer.Write (type.FullName);
+#if NET_4_0
+                                       string asmName = GetForwardedAttribute.GetAssemblyName(type);
+                                       writer.Write ((int) GetAssemblyNameId (asmName));
+#else
                                        writer.Write ((int)GetAssemblyId (type.Assembly));
+#endif
                                        break;
 
                                case TypeTag.ArrayOfPrimitiveType: