X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Runtime.Serialization.Formatters.Binary%2FObjectReader.cs;h=134b936a3e1ed8e89bfa126cf0967ec4e932534d;hb=9e3370d3351358044231dd1f3df5fff3720bdcc2;hp=b222efd013c304898b2ecb2cce17d60080bee90b;hpb=032fcf581ee7ff6969d673e60755446796a63bc2;p=mono.git diff --git a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs index b222efd013c..134b936a3e1 100644 --- a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs +++ b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs @@ -5,8 +5,29 @@ // Patrik Torstensson // // (C) 2003 Lluis Sanchez Gual - -// FIXME: Implement the missing binary elements + +// +// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// using System; using System.Runtime.Serialization; @@ -14,13 +35,20 @@ using System.IO; using System.Collections; using System.Reflection; using System.Runtime.Remoting.Messaging; +using System.Globalization; namespace System.Runtime.Serialization.Formatters.Binary { internal class ObjectReader { + BinaryFormatter _formatter; ISurrogateSelector _surrogateSelector; StreamingContext _context; + SerializationBinder _binder; + +#if NET_1_1 + TypeFilterLevel _filterLevel; +#endif ObjectManager _manager; Hashtable _registeredAssemblies = new Hashtable(); @@ -35,6 +63,7 @@ namespace System.Runtime.Serialization.Formatters.Binary public Type Type; public Type[] MemberTypes; public string[] MemberNames; + public MemberInfo[] MemberInfos; public int FieldCount; public bool NeedsSerializationInfo; } @@ -45,16 +74,22 @@ namespace System.Runtime.Serialization.Formatters.Binary public int NullCount; } - public ObjectReader(ISurrogateSelector surrogateSelector, StreamingContext context) + public ObjectReader (BinaryFormatter formatter) { - _manager = new ObjectManager (surrogateSelector, context); - _surrogateSelector = surrogateSelector; - _context = context; + _formatter = formatter; + _surrogateSelector = formatter.SurrogateSelector; + _context = formatter.Context; + _binder = formatter.Binder; + _manager = new ObjectManager (_surrogateSelector, _context); + +#if NET_1_1 + _filterLevel = formatter.FilterLevel; +#endif } - public object ReadObjectGraph (BinaryReader reader, bool readHeaders, HeaderHandler headerHandler) + public void ReadObjectGraph (BinaryReader reader, bool readHeaders, out object result, out Header[] headers) { - Header[] headers = null; + headers = null; // Reads the objects. The first object in the stream is the // root object. @@ -67,10 +102,7 @@ namespace System.Runtime.Serialization.Formatters.Binary if (_rootObjectID == 0) _rootObjectID = _lastObjectID; } - if (readHeaders && headerHandler != null) - headerHandler (headers); - - return _manager.GetObject (_rootObjectID); + result = _manager.GetObject (_rootObjectID); } public bool ReadNextObject (BinaryReader reader) @@ -79,6 +111,7 @@ namespace System.Runtime.Serialization.Formatters.Binary if (element == BinaryElement.End) { _manager.DoFixups(); + _manager.RaiseDeserializationEvent(); return false; } @@ -132,6 +165,7 @@ namespace System.Runtime.Serialization.Formatters.Binary ReadGenericArray (reader, out objectId, out value); break; + case BinaryElement.BoxedPrimitiveTypeValue: value = ReadBoxedPrimitiveTypeValue (reader); objectId = 0; @@ -185,8 +219,7 @@ namespace System.Runtime.Serialization.Formatters.Binary { long id = (long) reader.ReadUInt32 (); string assemblyName = reader.ReadString (); - Assembly assembly = Assembly.Load (assemblyName); - _registeredAssemblies [id] = assembly; + _registeredAssemblies [id] = assemblyName; } private void ReadObjectInstance (BinaryReader reader, bool isRuntimeObject, out long objectId, out object value, out SerializationInfo info) @@ -213,11 +246,21 @@ namespace System.Runtime.Serialization.Formatters.Binary private void ReadObjectContent (BinaryReader reader, TypeMetadata metadata, long objectId, out object objectInstance, out SerializationInfo info) { - objectInstance = FormatterServices.GetUninitializedObject (metadata.Type); +#if NET_1_1 + if (_filterLevel == TypeFilterLevel.Low) + objectInstance = FormatterServices.GetSafeUninitializedObject (metadata.Type); + else +#endif + objectInstance = FormatterServices.GetUninitializedObject (metadata.Type); + info = metadata.NeedsSerializationInfo ? new SerializationInfo(metadata.Type, new FormatterConverter()) : null; - for (int n=0; n= 0; dim--) { @@ -333,7 +376,7 @@ namespace System.Runtime.Serialization.Formatters.Binary for (int n = 0; n < length; n++) { indices[0] = n; - ReadValue (reader, array, objectId, null, elementType, null, indices); + ReadValue (reader, array, objectId, null, elementType, null, null, indices); n = indices[0]; } val = array; @@ -365,8 +408,7 @@ namespace System.Runtime.Serialization.Formatters.Binary if (!isRuntimeObject) { long assemblyId = (long)reader.ReadUInt32(); - Assembly asm = (Assembly)_registeredAssemblies[assemblyId]; - metadata.Type = asm.GetType (className, true); + metadata.Type = GetDeserializationType (assemblyId, className); } else metadata.Type = Type.GetType (className, true); @@ -395,6 +437,37 @@ namespace System.Runtime.Serialization.Formatters.Binary throw new SerializationException("Serializable objects must be marked with the Serializable attribute"); metadata.NeedsSerializationInfo = (metadata.Type.GetInterface ("ISerializable") != null); + if (!metadata.NeedsSerializationInfo) + { + metadata.MemberInfos = new MemberInfo [fieldCount]; + for (int n=0; n 1) throw new SerializationException ("There are two public members named \"" + names[n] + "\" in the class hirearchy of " + metadata.Type.FullName); + metadata.MemberInfos [n] = members[0]; + } + metadata.MemberNames = null; // Info now in MemberInfos + } } // Registers the type's metadata so it can be reused later if @@ -407,7 +480,7 @@ namespace System.Runtime.Serialization.Formatters.Binary } - private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, int[] indices) + private void ReadValue (BinaryReader reader, object parentObject, long parentObjectId, SerializationInfo info, Type valueType, string fieldName, MemberInfo memberInfo, int[] indices) { // Reads a value from the stream and assigns it to the member of an object @@ -416,7 +489,7 @@ namespace System.Runtime.Serialization.Formatters.Binary if (BinaryCommon.IsPrimitive (valueType)) { val = ReadPrimitiveTypeValue (reader, valueType); - SetObjectValue (parentObject, fieldName, info, val, valueType, indices); + SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices); return; } @@ -428,7 +501,7 @@ namespace System.Runtime.Serialization.Formatters.Binary { // Just read the id of the referred object and record a fixup long childObjectId = (long) reader.ReadUInt32(); - RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, indices); + RecordFixup (parentObjectId, childObjectId, parentObject, info, fieldName, memberInfo, indices); return; } @@ -455,29 +528,29 @@ namespace System.Runtime.Serialization.Formatters.Binary { if (val.GetType().IsValueType) { - RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, indices); + RecordFixup (parentObjectId, objectId, parentObject, info, fieldName, memberInfo, indices); hasFixup = true; } // Register the value - if (info == null && !parentObject.GetType().IsArray) - RegisterObject (objectId, val, objectInfo, parentObjectId, GetObjectMember(parentObject, fieldName), null); + if (info == null && !(parentObject is Array)) + RegisterObject (objectId, val, objectInfo, parentObjectId, memberInfo, null); else RegisterObject (objectId, val, objectInfo, parentObjectId, null, indices); } // Assign the value to the parent object, unless there is a fixup if (!hasFixup) - SetObjectValue (parentObject, fieldName, info, val, valueType, indices); + SetObjectValue (parentObject, fieldName, memberInfo, info, val, valueType, indices); } - private void SetObjectValue (object parentObject, string fieldName, SerializationInfo info, object value, Type valueType, int[] indices) + private void SetObjectValue (object parentObject, string fieldName, MemberInfo memberInfo, SerializationInfo info, object value, Type valueType, int[] indices) { if (value is IObjectReference) value = ((IObjectReference)value).GetRealObject (_context); - if (parentObject.GetType().IsArray) + if (parentObject is Array) { if (value is ArrayNullFiller) { @@ -493,36 +566,40 @@ namespace System.Runtime.Serialization.Formatters.Binary info.AddValue (fieldName, value, valueType); } else { - MemberInfo member = GetObjectMember(parentObject, fieldName); - if (member is FieldInfo) - ((FieldInfo)member).SetValue (parentObject, value); + if (memberInfo is FieldInfo) + ((FieldInfo)memberInfo).SetValue (parentObject, value); else - ((PropertyInfo)member).SetValue (parentObject, value, null); + ((PropertyInfo)memberInfo).SetValue (parentObject, value, null); } } - private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, int[] indices) + private void RecordFixup (long parentObjectId, long childObjectId, object parentObject, SerializationInfo info, string fieldName, MemberInfo memberInfo, int[] indices) { if (info != null) { _manager.RecordDelayedFixup (parentObjectId, fieldName, childObjectId); } - else if (parentObject.GetType().IsArray) { + else if (parentObject is Array) { if (indices.Length == 1) _manager.RecordArrayElementFixup (parentObjectId, indices[0], childObjectId); else _manager.RecordArrayElementFixup (parentObjectId, (int[])indices.Clone(), childObjectId); } else { - _manager.RecordFixup (parentObjectId, GetObjectMember(parentObject, fieldName), childObjectId); + _manager.RecordFixup (parentObjectId, memberInfo, childObjectId); } } - private MemberInfo GetObjectMember (object parentObject, string fieldName) + private Type GetDeserializationType (long assemblyId, string className) { - MemberInfo[] members = parentObject.GetType().GetMember (fieldName, MemberTypes.Field | MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - if (members.Length > 1) throw new SerializationException ("There are two public members named \"" + fieldName + "\" in the class hirearchy of " + parentObject.GetType().FullName); - if (members.Length == 0) throw new SerializationException ("Field \"" + fieldName + "\" not found in class " + parentObject.GetType().FullName); - return members[0]; + string assemblyName = (string)_registeredAssemblies[assemblyId]; + + if (_binder == null) + { + Assembly assembly = Assembly.Load (assemblyName); + return assembly.GetType (className, true); + } + else + return _binder.BindToType (assemblyName, className); } public Type ReadType (BinaryReader reader, TypeTag code) @@ -548,8 +625,7 @@ namespace System.Runtime.Serialization.Formatters.Binary { string name = reader.ReadString (); long asmid = (long) reader.ReadUInt32(); - Assembly asm = (Assembly)_registeredAssemblies[asmid]; - return asm.GetType (name, true); + return GetDeserializationType (asmid, name); } case TypeTag.ArrayOfObject: @@ -583,11 +659,10 @@ namespace System.Runtime.Serialization.Formatters.Binary return reader.ReadChar(); case TypeCode.DateTime: - long ticks = reader.ReadInt64(); - return new DateTime (ticks); + return new DateTime (reader.ReadInt64()); case TypeCode.Decimal: - return reader.ReadDecimal(); + return Decimal.Parse (reader.ReadString(), CultureInfo.InvariantCulture); case TypeCode.Double: return reader.ReadDouble(); @@ -620,8 +695,11 @@ namespace System.Runtime.Serialization.Formatters.Binary return reader.ReadString(); default: - throw new NotSupportedException ("Unsupported primitive type: " + type.FullName); + if (type == typeof(TimeSpan)) + return new TimeSpan (reader.ReadInt64 ()); + else + throw new NotSupportedException ("Unsupported primitive type: " + type.FullName); } } } -} +}