From: Miguel de Icaza Date: Fri, 26 Apr 2013 16:55:22 +0000 (-0700) Subject: Merge pull request #615 from nealef/master X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=ce6acbe4db3caca1d54f08f9758a88a7768ff236;hp=7f0328f12ae9b91c9adc5dd0c9ce0fc770f81a06;p=mono.git Merge pull request #615 from nealef/master Fix incompatibility with .NET's serialization of ObservableCollection --- diff --git a/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs b/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs index 6c26e8795f6..32926907e21 100644 --- a/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs +++ b/mcs/class/System/System.Collections.ObjectModel/ObservableCollection.cs @@ -40,30 +40,33 @@ namespace System.Collections.ObjectModel #endif public class ObservableCollection : Collection, 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."); } diff --git a/mcs/class/WindowsBase/System.Collections.ObjectModel/ObservableCollection.cs b/mcs/class/WindowsBase/System.Collections.ObjectModel/ObservableCollection.cs index 1ea166cd9ac..bcc4440e109 100644 --- a/mcs/class/WindowsBase/System.Collections.ObjectModel/ObservableCollection.cs +++ b/mcs/class/WindowsBase/System.Collections.ObjectModel/ObservableCollection.cs @@ -44,7 +44,7 @@ namespace System.Collections.ObjectModel public class ObservableCollection : Collection, 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; } } } diff --git a/mcs/class/corlib/System.Collections.ObjectModel/Collection.cs b/mcs/class/corlib/System.Collections.ObjectModel/Collection.cs index 6a57a75acba..b9d6a3e71e4 100644 --- a/mcs/class/corlib/System.Collections.ObjectModel/Collection.cs +++ b/mcs/class/corlib/System.Collections.ObjectModel/Collection.cs @@ -53,8 +53,7 @@ namespace System.Collections.ObjectModel , IReadOnlyList #endif { - IList items; - [field:NonSerializedAttribute()] + IList list; object syncRoot; public Collection () @@ -62,21 +61,21 @@ namespace System.Collections.ObjectModel List l = new List (); IList l2 = l as IList; syncRoot = l2.SyncRoot; - items = l; + list = l; } - public Collection (IList items) + public Collection (IList 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 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 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.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 items) + internal static void CheckWritable (IList list) { - if (items.IsReadOnly) + if (list.IsReadOnly) throw new NotSupportedException (); } - internal static bool IsSynchronized (IList items) + internal static bool IsSynchronized (IList list) { - ICollection c = items as ICollection; + ICollection c = list as ICollection; return (c != null) ? c.IsSynchronized : false; } - internal static bool IsFixedSize (IList items) + internal static bool IsFixedSize (IList 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 (value)) - return items.Contains ((T) value); + return list.Contains ((T) value); return false; } int IList.IndexOf (object value) { if (CollectionHelpers.IsValidItem (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 diff --git a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs index fd38471644b..671c196163e 100644 --- a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs +++ b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenerator.cs @@ -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); diff --git a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs index 9d3c42bbd19..c5bf658a1c8 100644 --- a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs +++ b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectWriter.cs @@ -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: