diff options
author | Neale <neale@sinenomine.net> | 2013-04-17 06:27:47 +0400 |
---|---|---|
committer | Neale <neale@sinenomine.net> | 2013-04-17 06:27:47 +0400 |
commit | f19a364025edc23559597e24ea332890f3b1e0ff (patch) | |
tree | 8fa5d5d37820b101b5abfdf335bd616193ce880a | |
parent | 1f739060e594cc427676bd36ebf8bb8701736023 (diff) |
When .NET serializes it will use the TypeForwardedFrom information whenmono-3.0.10-windows
writing Assembly information but Mono does not. This means that
serialized objects created on one platform are not able to be
deserialized on the other, thus preventing interoperability between .NET
and mono applications. Fixes the ObservableCollection part of bugzilla
11294.
4 files changed, 78 insertions, 18 deletions
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<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."); } 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<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; } } } 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: |