From 4d8f3a4759e09ca4a59890356d42cbafd9a2fd24 Mon Sep 17 00:00:00 2001 From: Evgeny Rokhlin Date: Wed, 2 Jan 2013 14:15:28 +1100 Subject: [PATCH] Fixed deserializing of Arrays of Enum values Found a bug when attempting to deserialize an array of Enum values. Added a unit test project, added a failing unit test Serializes_Deserializes_Array_Of_EnumValues, added a fix, verified that the unit test passes. --- Local.testsettings | 10 + Serialization.SL/SerializationUnits.cs | 1217 +++++++++-------- .../Properties/AssemblyInfo.cs | 35 + .../Serialization.UnitTests.csproj | 65 + .../SerializerUnitTests.cs | 28 + Serialization.sln | 140 +- Serialization.vsmdi | 6 + TraceAndTestImpact.testsettings | 9 + 8 files changed, 850 insertions(+), 660 deletions(-) create mode 100644 Local.testsettings create mode 100644 Serialization.UnitTests/Properties/AssemblyInfo.cs create mode 100644 Serialization.UnitTests/Serialization.UnitTests.csproj create mode 100644 Serialization.UnitTests/SerializerUnitTests.cs create mode 100644 Serialization.vsmdi create mode 100644 TraceAndTestImpact.testsettings diff --git a/Local.testsettings b/Local.testsettings new file mode 100644 index 0000000..872ec69 --- /dev/null +++ b/Local.testsettings @@ -0,0 +1,10 @@ + + + These are default test settings for a local test run. + + + + + + + \ No newline at end of file diff --git a/Serialization.SL/SerializationUnits.cs b/Serialization.SL/SerializationUnits.cs index ce038e0..8aa7c27 100644 --- a/Serialization.SL/SerializationUnits.cs +++ b/Serialization.SL/SerializationUnits.cs @@ -1,599 +1,618 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace Serialization -{ - - - public class Entry - { - /// - /// The name of the item being read or written - /// This should be filled out by the storage when - /// MustHaveName = true and deserializing - /// - public string Name; - /// - /// The type of the item being stored or retrieved - /// this should be filled out by the storage when - /// MustHaveName=true and deserializing. Will - /// be filled in when serializing. - /// - private PropertyInfo _propertyInfo; - private FieldInfo _fieldInfo; - public Type StoredType; - /// - /// On writing, the value of the object for reference, not needed on - /// deserialization - /// - public object Value; - /// - /// Set to indicate that the name provided is that of a field or property - /// and is needed to reset the value later - /// - public bool MustHaveName; - /// - /// The type of the object which owns the item being serialized or null - /// if not directly owned. This will always be set on serialization and - /// deserialization when MustHaveName = true and can be used to - /// look up field and property information. Or you can ignore it if - /// you don't need it - /// - public Type OwningType; - /// - /// The property info or null, if the value did not - /// come from a property. You might want to use - /// the to look up attributes attached to the property - /// definition - /// - public PropertyInfo PropertyInfo - { - get { return _propertyInfo; } - set - { - Name = value.Name; - StoredType = value.PropertyType; - - _propertyInfo = value; - } - } - /// - /// The field info or null, if the value did not - /// come from a field. You might want to use it - /// to look up attributes attached to the field definition - /// - public FieldInfo FieldInfo - { - get - { - - return _fieldInfo; - } - set - { - Name = value.Name; - StoredType = value.FieldType; - _fieldInfo = value; - } - } - - public GetSet Setter; - } - - public class BinarySerializer : IStorage - { - public byte[] Data { get; private set; } - private MemoryStream _myStream; - - - /// - /// Used when serializing - /// - public BinarySerializer() - { - - } - /// - /// Used when deserializaing - /// - /// - public BinarySerializer(byte[] data) - { - Data = data; - } - - - #region writing - - private BinaryWriter _writer; - private void EncodeType(object item, Type storedType) - { - - if (item == null) - { - WriteSimpleValue((ushort)0xFFFE); - return; - } - - var itemType = item.GetType().TypeHandle; - - //If this isn't a simple type, then this might be a subclass so we need to - //store the type - if (storedType == null || !storedType.Equals(item.GetType()) || SilverlightSerializer.Verbose) - { - //Write the type identifier - var tpId = SilverlightSerializer.GetTypeId(itemType); - WriteSimpleValue(tpId); - } - else - //Write a dummy identifier - WriteSimpleValue((ushort)0xFFFF); - - } - - public bool StartSerializing(Entry entry, int id) - { - if (entry.MustHaveName) - { - ushort nameID = SilverlightSerializer.GetPropertyDefinitionId(entry.Name); - WriteSimpleValue(nameID); - } - var item = entry.Value ?? new SilverlightSerializer.Nuller(); - EncodeType(item, entry.StoredType); - return false; - } - - - - - - - - public void StartSerializing() - { - _myStream = new MemoryStream(); - _writer = new BinaryWriter(_myStream); - SilverlightSerializer.KtStack.Push(SilverlightSerializer.KnownTypes); - SilverlightSerializer.PiStack.Push(SilverlightSerializer.PropertyIds); - SilverlightSerializer.KnownTypes = new List(); - SilverlightSerializer.PropertyIds = new List(); - } - - - - - - public void FinishedSerializing() - { - _writer.Flush(); - _writer.Close(); - _myStream.Flush(); - var data = _myStream.ToArray(); - _myStream.Close(); - _myStream = null; - - var stream = new MemoryStream(); - var outputWr = new BinaryWriter(stream); - outputWr.Write("SerV7"); - //New, store the verbose property - outputWr.Write(SilverlightSerializer.Verbose); - outputWr.Write(SilverlightSerializer.KnownTypes.Count); - foreach (var kt in SilverlightSerializer.KnownTypes.Select(Type.GetTypeFromHandle)) - { - outputWr.Write(kt.AssemblyQualifiedName); - } - outputWr.Write(SilverlightSerializer.PropertyIds.Count); - foreach (var pi in SilverlightSerializer.PropertyIds) - { - outputWr.Write(pi); - } - - outputWr.Write(data.Length); - outputWr.Write(data); - outputWr.Flush(); - outputWr.Close(); - stream.Flush(); - - Data = stream.ToArray(); - stream.Close(); - _writer = null; - _reader = null; - - SilverlightSerializer.KnownTypes = SilverlightSerializer.KtStack.Pop(); - SilverlightSerializer.PropertyIds = SilverlightSerializer.PiStack.Pop(); - - } - - - - public bool SupportsOnDemand - { - get { return false; } - } - public void BeginOnDemand(int id) { } - public void EndOnDemand() { } - - - - public void BeginWriteObject(int id, Type objectType, bool wasSeen) - { - if (wasSeen) - { - WriteSimpleValue('S'); - WriteSimpleValue(id); - } - else - { - WriteSimpleValue('O'); - } - } - - - - - - - public void BeginWriteProperties(int count) - { - WriteSimpleValue((byte)count); - } - public void BeginWriteFields(int count) - { - WriteSimpleValue((byte)count); - } - public void WriteSimpleValue(object value) - { - SilverlightSerializer.WriteValue(_writer, value); - } - public void BeginWriteList(int count, Type listType) - { - WriteSimpleValue(count); - } - public void BeginWriteDictionary(int count, Type dictionaryType) - { - WriteSimpleValue(count); - } - - - - public void WriteSimpleArray(int count, Array array) - { - WriteSimpleValue(count); - - var elementType = array.GetType().GetElementType(); - if (elementType == typeof(byte)) - { - WriteSimpleValue((byte[])array); - } - else if (elementType.IsPrimitive) - { - var ba = new byte[Buffer.ByteLength(array)]; - Buffer.BlockCopy(array, 0, ba, 0, ba.Length); - WriteSimpleValue(ba); - } - else - { - for (int i = 0; i < count; i++) - { - WriteSimpleValue(array.GetValue(i)); - } - } - } - - - public void BeginMultiDimensionArray(Type arrayType, int dimensions, int count) - { - WriteSimpleValue(-1); - WriteSimpleValue(dimensions); - WriteSimpleValue(count); - } - public void WriteArrayDimension(int dimension, int count) - { - WriteSimpleValue(count); - } - public void BeginWriteObjectArray(int count, Type arrayType) - { - WriteSimpleValue(count); - } - - public Entry[] ShouldWriteFields(Entry[] fields) { return fields; } - public Entry[] ShouldWriteProperties(Entry[] properties) { return properties; } - - - - - #endregion writing - - - - #region reading - - private BinaryReader _reader; - private Type DecodeType(Type storedType) - { - ushort tid = this.ReadSimpleValue(); - if (tid == 0xFFFE) - { - return null; - } - if (tid != 0xffff) - { - storedType = Type.GetTypeFromHandle(SilverlightSerializer.KnownTypes[tid]); - } - return storedType; - - } - - public void FinishedDeserializing() - { - _reader.Close(); - _myStream.Close(); - _reader = null; - _myStream = null; - _writer = null; - SilverlightSerializer.KnownTypes = SilverlightSerializer.KtStack.Pop(); - SilverlightSerializer.PropertyIds = SilverlightSerializer.PiStack.Pop(); - } - - //Gets the name from the stream - public void DeserializeGetName(Entry entry) - { - if (entry.MustHaveName) - { - ushort id = this.ReadSimpleValue(); - entry.Name = SilverlightSerializer.PropertyIds[id]; - } - } - - /// - /// Starts to deserialize the object - /// - /// - /// - public object StartDeserializing(Entry entry) - { - var itemType = DecodeType(entry.StoredType); - entry.StoredType = itemType; - return null; - } - - - public Entry BeginReadProperty(Entry entry) - { - return entry; - } - public void EndReadProeprty() - { - - } - public Entry BeginReadField(Entry entry) - { - return entry; - } - public void EndReadField() - { - - } - - public void StartDeserializing() - { - SilverlightSerializer.KtStack.Push(SilverlightSerializer.KnownTypes); - SilverlightSerializer.PiStack.Push(SilverlightSerializer.PropertyIds); - - var stream = new MemoryStream(Data); - var reader = new BinaryReader(stream); - var version = reader.ReadString(); - SilverlightSerializer.currentVersion = int.Parse(version.Substring(4)); - if (SilverlightSerializer.currentVersion >= 3) - SilverlightSerializer.Verbose = reader.ReadBoolean(); - - SilverlightSerializer.PropertyIds = new List(); - SilverlightSerializer.KnownTypes = new List(); - var count = reader.ReadInt32(); - for (var i = 0; i < count; i++) - { - var typeName = reader.ReadString(); - var tp = Type.GetType(typeName); - if (tp == null) - { - var map = new SilverlightSerializer.TypeMappingEventArgs - { - TypeName = typeName - }; - SilverlightSerializer.InvokeMapMissingType(map); - tp = map.UseType; - } - if (tp == null) - throw new ArgumentException(string.Format("Cannot reference type {0} in this context", typeName)); - SilverlightSerializer.KnownTypes.Add(tp.TypeHandle); - } - count = reader.ReadInt32(); - for (var i = 0; i < count; i++) - { - SilverlightSerializer.PropertyIds.Add(reader.ReadString()); - } - - var data = reader.ReadBytes(reader.ReadInt32()); - - _myStream = new MemoryStream(data); - _reader = new BinaryReader(_myStream); - reader.Close(); - stream.Close(); - } - - public void FinishDeserializing(Entry entry) { } - - - - - - public Array ReadSimpleArray(Type elementType, int count) - { - if (count == -1) - { - count = ReadSimpleValue(); - } - - if (elementType == typeof(byte)) - { - return ReadSimpleValue(); - } - if (elementType.IsPrimitive && SilverlightSerializer.currentVersion >= 6) - { - var ba = ReadSimpleValue(); - var a = Array.CreateInstance(elementType, count); - Buffer.BlockCopy(ba, 0, a, 0, ba.Length); - return a; - } - var result = Array.CreateInstance(elementType, count); - for (var l = 0; l < count; l++) - { - result.SetValue(this.ReadSimpleValue(elementType), l); - } - return result; - } - - public int BeginReadProperties() - { - return this.ReadSimpleValue(); - } - public int BeginReadFields() - { - return this.ReadSimpleValue(); - } - - - public T ReadSimpleValue() - { - return (T)ReadSimpleValue(typeof(T)); - } - public object ReadSimpleValue(Type type) - { - SilverlightSerializer.ReadAValue read; - if (!SilverlightSerializer.Readers.TryGetValue(type, out read)) - { - return _reader.ReadInt32(); - } - return read(_reader); - - } - - public bool IsMultiDimensionalArray(out int length) - { - var count = ReadSimpleValue(); - if (count == -1) - { - length = -1; - return true; - } - length = count; - return false; - } - - public int BeginReadDictionary() - { - return ReadSimpleValue(); ; - } - public void EndReadDictionary() { } - - public int BeginReadObjectArray() - { - return ReadSimpleValue(); - } - public void EndReadObjectArray() { } - - - public void BeginReadMultiDimensionalArray(out int dimension, out int count) - { - // - //var dimensions = storage.ReadValue("dimensions"); - //var totalLength = storage.ReadValue("length"); - dimension = ReadSimpleValue(); - count = ReadSimpleValue(); - } - public void EndReadMultiDimensionalArray() { } - - public int ReadArrayDimension(int index) - { - // //.ReadValue("dim_len" + item); - return ReadSimpleValue(); - } - - - public int BeginReadList() - { - return ReadSimpleValue(); - } - public void EndReadList() { } - - private int _currentObjectID = 0; - public int BeginReadObject(out bool isReference) - { - int result; - char knownType = this.ReadSimpleValue(); - if (knownType == 'O') - { - result = _currentObjectID; - _currentObjectID++; - isReference = false; - } - else - { - result = this.ReadSimpleValue(); - isReference = true; - } - - return result; - } - - - #endregion reading - - - - #region do nothing methods - - public void EndWriteObjectArray() { } - public void EndWriteList() { } - public void EndWriteDictionary() { } - public void BeginWriteDictionaryKey(int id) { } - public void EndWriteDictionaryKey() { } - public void BeginWriteDictionaryValue(int id) { } - public void EndWriteDictionaryValue() { } - public void EndMultiDimensionArray() { } - public void EndReadObject() { } - public void BeginWriteListItem(int index) { } - public void EndWriteListItem() { } - public void BeginWriteObjectArrayItem(int index) { } - public void EndWriteObjectArrayItem() { } - public void EndReadProperties() { } - public void EndReadFields() { } - public void BeginReadListItem(int index) { } - public void EndReadListItem() { } - public void BeginReadDictionaryKeyItem(int index) { } - public void EndReadDictionaryKeyItem() { } - public void BeginReadDictionaryValueItem(int index) { } - public void EndReadDictionaryValueItem() { } - public void BeginReadObjectArrayItem(int index) { } - public void EndReadObjectArrayItem() { } - public void EndWriteObject() { } - public void BeginWriteProperty(string name, Type type) { } - public void EndWriteProperty() { } - public void BeginWriteField(string name, Type type) { } - public void EndWriteField() { } - public void EndWriteProperties() { } - public void EndWriteFields() { } - public void FinishSerializing(Entry entry) { } - - - #endregion do nothing methods - - - - } - - -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace Serialization +{ + + + public class Entry + { + /// + /// The name of the item being read or written + /// This should be filled out by the storage when + /// MustHaveName = true and deserializing + /// + public string Name; + /// + /// The type of the item being stored or retrieved + /// this should be filled out by the storage when + /// MustHaveName=true and deserializing. Will + /// be filled in when serializing. + /// + private PropertyInfo _propertyInfo; + private FieldInfo _fieldInfo; + public Type StoredType; + /// + /// On writing, the value of the object for reference, not needed on + /// deserialization + /// + public object Value; + /// + /// Set to indicate that the name provided is that of a field or property + /// and is needed to reset the value later + /// + public bool MustHaveName; + /// + /// The type of the object which owns the item being serialized or null + /// if not directly owned. This will always be set on serialization and + /// deserialization when MustHaveName = true and can be used to + /// look up field and property information. Or you can ignore it if + /// you don't need it + /// + public Type OwningType; + /// + /// The property info or null, if the value did not + /// come from a property. You might want to use + /// the to look up attributes attached to the property + /// definition + /// + public PropertyInfo PropertyInfo + { + get { return _propertyInfo; } + set + { + Name = value.Name; + StoredType = value.PropertyType; + + _propertyInfo = value; + } + } + /// + /// The field info or null, if the value did not + /// come from a field. You might want to use it + /// to look up attributes attached to the field definition + /// + public FieldInfo FieldInfo + { + get + { + + return _fieldInfo; + } + set + { + Name = value.Name; + StoredType = value.FieldType; + _fieldInfo = value; + } + } + + public GetSet Setter; + } + + public class BinarySerializer : IStorage + { + public byte[] Data { get; private set; } + private MemoryStream _myStream; + + + /// + /// Used when serializing + /// + public BinarySerializer() + { + + } + /// + /// Used when deserializaing + /// + /// + public BinarySerializer(byte[] data) + { + Data = data; + } + + + #region writing + + private BinaryWriter _writer; + private void EncodeType(object item, Type storedType) + { + + if (item == null) + { + WriteSimpleValue((ushort)0xFFFE); + return; + } + + var itemType = item.GetType().TypeHandle; + + //If this isn't a simple type, then this might be a subclass so we need to + //store the type + if (storedType == null || !storedType.Equals(item.GetType()) || SilverlightSerializer.Verbose) + { + //Write the type identifier + var tpId = SilverlightSerializer.GetTypeId(itemType); + WriteSimpleValue(tpId); + } + else + //Write a dummy identifier + WriteSimpleValue((ushort)0xFFFF); + + } + + public bool StartSerializing(Entry entry, int id) + { + if (entry.MustHaveName) + { + ushort nameID = SilverlightSerializer.GetPropertyDefinitionId(entry.Name); + WriteSimpleValue(nameID); + } + var item = entry.Value ?? new SilverlightSerializer.Nuller(); + EncodeType(item, entry.StoredType); + return false; + } + + + + + + + + public void StartSerializing() + { + _myStream = new MemoryStream(); + _writer = new BinaryWriter(_myStream); + SilverlightSerializer.KtStack.Push(SilverlightSerializer.KnownTypes); + SilverlightSerializer.PiStack.Push(SilverlightSerializer.PropertyIds); + SilverlightSerializer.KnownTypes = new List(); + SilverlightSerializer.PropertyIds = new List(); + } + + + + + + public void FinishedSerializing() + { + _writer.Flush(); + _writer.Close(); + _myStream.Flush(); + var data = _myStream.ToArray(); + _myStream.Close(); + _myStream = null; + + var stream = new MemoryStream(); + var outputWr = new BinaryWriter(stream); + outputWr.Write("SerV7"); + //New, store the verbose property + outputWr.Write(SilverlightSerializer.Verbose); + outputWr.Write(SilverlightSerializer.KnownTypes.Count); + foreach (var kt in SilverlightSerializer.KnownTypes.Select(Type.GetTypeFromHandle)) + { + outputWr.Write(kt.AssemblyQualifiedName); + } + outputWr.Write(SilverlightSerializer.PropertyIds.Count); + foreach (var pi in SilverlightSerializer.PropertyIds) + { + outputWr.Write(pi); + } + + outputWr.Write(data.Length); + outputWr.Write(data); + outputWr.Flush(); + outputWr.Close(); + stream.Flush(); + + Data = stream.ToArray(); + stream.Close(); + _writer = null; + _reader = null; + + SilverlightSerializer.KnownTypes = SilverlightSerializer.KtStack.Pop(); + SilverlightSerializer.PropertyIds = SilverlightSerializer.PiStack.Pop(); + + } + + + + public bool SupportsOnDemand + { + get { return false; } + } + public void BeginOnDemand(int id) { } + public void EndOnDemand() { } + + + + public void BeginWriteObject(int id, Type objectType, bool wasSeen) + { + if (wasSeen) + { + WriteSimpleValue('S'); + WriteSimpleValue(id); + } + else + { + WriteSimpleValue('O'); + } + } + + + + + + + public void BeginWriteProperties(int count) + { + WriteSimpleValue((byte)count); + } + public void BeginWriteFields(int count) + { + WriteSimpleValue((byte)count); + } + public void WriteSimpleValue(object value) + { + SilverlightSerializer.WriteValue(_writer, value); + } + public void BeginWriteList(int count, Type listType) + { + WriteSimpleValue(count); + } + public void BeginWriteDictionary(int count, Type dictionaryType) + { + WriteSimpleValue(count); + } + + + + public void WriteSimpleArray(int count, Array array) + { + WriteSimpleValue(count); + + var elementType = array.GetType().GetElementType(); + if (elementType == typeof(byte)) + { + WriteSimpleValue((byte[])array); + } + else if (elementType.IsPrimitive) + { + var ba = new byte[Buffer.ByteLength(array)]; + Buffer.BlockCopy(array, 0, ba, 0, ba.Length); + WriteSimpleValue(ba); + } + else + { + for (int i = 0; i < count; i++) + { + WriteSimpleValue(array.GetValue(i)); + } + } + } + + + public void BeginMultiDimensionArray(Type arrayType, int dimensions, int count) + { + WriteSimpleValue(-1); + WriteSimpleValue(dimensions); + WriteSimpleValue(count); + } + public void WriteArrayDimension(int dimension, int count) + { + WriteSimpleValue(count); + } + public void BeginWriteObjectArray(int count, Type arrayType) + { + WriteSimpleValue(count); + } + + public Entry[] ShouldWriteFields(Entry[] fields) { return fields; } + public Entry[] ShouldWriteProperties(Entry[] properties) { return properties; } + + + + + #endregion writing + + + + #region reading + + private BinaryReader _reader; + private Type DecodeType(Type storedType) + { + ushort tid = this.ReadSimpleValue(); + if (tid == 0xFFFE) + { + return null; + } + if (tid != 0xffff) + { + storedType = Type.GetTypeFromHandle(SilverlightSerializer.KnownTypes[tid]); + } + return storedType; + + } + + public void FinishedDeserializing() + { + _reader.Close(); + _myStream.Close(); + _reader = null; + _myStream = null; + _writer = null; + SilverlightSerializer.KnownTypes = SilverlightSerializer.KtStack.Pop(); + SilverlightSerializer.PropertyIds = SilverlightSerializer.PiStack.Pop(); + } + + //Gets the name from the stream + public void DeserializeGetName(Entry entry) + { + if (entry.MustHaveName) + { + ushort id = this.ReadSimpleValue(); + entry.Name = SilverlightSerializer.PropertyIds[id]; + } + } + + /// + /// Starts to deserialize the object + /// + /// + /// + public object StartDeserializing(Entry entry) + { + var itemType = DecodeType(entry.StoredType); + entry.StoredType = itemType; + return null; + } + + + public Entry BeginReadProperty(Entry entry) + { + return entry; + } + public void EndReadProeprty() + { + + } + public Entry BeginReadField(Entry entry) + { + return entry; + } + public void EndReadField() + { + + } + + public void StartDeserializing() + { + SilverlightSerializer.KtStack.Push(SilverlightSerializer.KnownTypes); + SilverlightSerializer.PiStack.Push(SilverlightSerializer.PropertyIds); + + var stream = new MemoryStream(Data); + var reader = new BinaryReader(stream); + var version = reader.ReadString(); + SilverlightSerializer.currentVersion = int.Parse(version.Substring(4)); + if (SilverlightSerializer.currentVersion >= 3) + SilverlightSerializer.Verbose = reader.ReadBoolean(); + + SilverlightSerializer.PropertyIds = new List(); + SilverlightSerializer.KnownTypes = new List(); + var count = reader.ReadInt32(); + for (var i = 0; i < count; i++) + { + var typeName = reader.ReadString(); + var tp = Type.GetType(typeName); + if (tp == null) + { + var map = new SilverlightSerializer.TypeMappingEventArgs + { + TypeName = typeName + }; + SilverlightSerializer.InvokeMapMissingType(map); + tp = map.UseType; + } + if (tp == null) + throw new ArgumentException(string.Format("Cannot reference type {0} in this context", typeName)); + SilverlightSerializer.KnownTypes.Add(tp.TypeHandle); + } + count = reader.ReadInt32(); + for (var i = 0; i < count; i++) + { + SilverlightSerializer.PropertyIds.Add(reader.ReadString()); + } + + var data = reader.ReadBytes(reader.ReadInt32()); + + _myStream = new MemoryStream(data); + _reader = new BinaryReader(_myStream); + reader.Close(); + stream.Close(); + } + + public void FinishDeserializing(Entry entry) { } + + + + + + public Array ReadSimpleArray(Type elementType, int count) + { + if (count == -1) + { + count = ReadSimpleValue(); + } + + if (elementType == typeof(byte)) + { + return ReadSimpleValue(); + } + if (elementType.IsPrimitive && SilverlightSerializer.currentVersion >= 6) + { + var ba = ReadSimpleValue(); + var a = Array.CreateInstance(elementType, count); + Buffer.BlockCopy(ba, 0, a, 0, ba.Length); + return a; + } + var result = Array.CreateInstance(elementType, count); + + //fix for deserializing arrays of enum values + if (elementType.IsEnum) + { + for (var l = 0; l < count; l++) + { + object enumValue = ReadEnumValue(elementType); + result.SetValue(enumValue, l); + } + } + else + { + for (var l = 0; l < count; l++) + { + result.SetValue(this.ReadSimpleValue(elementType), l); + } + } + return result; + } + + private object ReadEnumValue(Type elementType) + { + var readValue = ReadSimpleValue(elementType); + return Enum.ToObject(elementType, readValue); + } + + public int BeginReadProperties() + { + return this.ReadSimpleValue(); + } + public int BeginReadFields() + { + return this.ReadSimpleValue(); + } + + + public T ReadSimpleValue() + { + return (T)ReadSimpleValue(typeof(T)); + } + public object ReadSimpleValue(Type type) + { + SilverlightSerializer.ReadAValue read; + if (!SilverlightSerializer.Readers.TryGetValue(type, out read)) + { + return _reader.ReadInt32(); + } + return read(_reader); + + } + + public bool IsMultiDimensionalArray(out int length) + { + var count = ReadSimpleValue(); + if (count == -1) + { + length = -1; + return true; + } + length = count; + return false; + } + + public int BeginReadDictionary() + { + return ReadSimpleValue(); ; + } + public void EndReadDictionary() { } + + public int BeginReadObjectArray() + { + return ReadSimpleValue(); + } + public void EndReadObjectArray() { } + + + public void BeginReadMultiDimensionalArray(out int dimension, out int count) + { + // + //var dimensions = storage.ReadValue("dimensions"); + //var totalLength = storage.ReadValue("length"); + dimension = ReadSimpleValue(); + count = ReadSimpleValue(); + } + public void EndReadMultiDimensionalArray() { } + + public int ReadArrayDimension(int index) + { + // //.ReadValue("dim_len" + item); + return ReadSimpleValue(); + } + + + public int BeginReadList() + { + return ReadSimpleValue(); + } + public void EndReadList() { } + + private int _currentObjectID = 0; + public int BeginReadObject(out bool isReference) + { + int result; + char knownType = this.ReadSimpleValue(); + if (knownType == 'O') + { + result = _currentObjectID; + _currentObjectID++; + isReference = false; + } + else + { + result = this.ReadSimpleValue(); + isReference = true; + } + + return result; + } + + + #endregion reading + + + + #region do nothing methods + + public void EndWriteObjectArray() { } + public void EndWriteList() { } + public void EndWriteDictionary() { } + public void BeginWriteDictionaryKey(int id) { } + public void EndWriteDictionaryKey() { } + public void BeginWriteDictionaryValue(int id) { } + public void EndWriteDictionaryValue() { } + public void EndMultiDimensionArray() { } + public void EndReadObject() { } + public void BeginWriteListItem(int index) { } + public void EndWriteListItem() { } + public void BeginWriteObjectArrayItem(int index) { } + public void EndWriteObjectArrayItem() { } + public void EndReadProperties() { } + public void EndReadFields() { } + public void BeginReadListItem(int index) { } + public void EndReadListItem() { } + public void BeginReadDictionaryKeyItem(int index) { } + public void EndReadDictionaryKeyItem() { } + public void BeginReadDictionaryValueItem(int index) { } + public void EndReadDictionaryValueItem() { } + public void BeginReadObjectArrayItem(int index) { } + public void EndReadObjectArrayItem() { } + public void EndWriteObject() { } + public void BeginWriteProperty(string name, Type type) { } + public void EndWriteProperty() { } + public void BeginWriteField(string name, Type type) { } + public void EndWriteField() { } + public void EndWriteProperties() { } + public void EndWriteFields() { } + public void FinishSerializing(Entry entry) { } + + + #endregion do nothing methods + + + + } + + +} diff --git a/Serialization.UnitTests/Properties/AssemblyInfo.cs b/Serialization.UnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4cfae0c --- /dev/null +++ b/Serialization.UnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Serialization.UnitTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Serialization.UnitTests")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("88b9c0ec-a956-4b21-9cea-3cd408a197c9")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Serialization.UnitTests/Serialization.UnitTests.csproj b/Serialization.UnitTests/Serialization.UnitTests.csproj new file mode 100644 index 0000000..698a40d --- /dev/null +++ b/Serialization.UnitTests/Serialization.UnitTests.csproj @@ -0,0 +1,65 @@ + + + + Debug + AnyCPU + + + 2.0 + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9} + Library + Properties + Serialization.UnitTests + Serialization.UnitTests + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + 3.5 + + + + + False + + + + + + + + + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED} + Serialization.SL + + + + + \ No newline at end of file diff --git a/Serialization.UnitTests/SerializerUnitTests.cs b/Serialization.UnitTests/SerializerUnitTests.cs new file mode 100644 index 0000000..a615727 --- /dev/null +++ b/Serialization.UnitTests/SerializerUnitTests.cs @@ -0,0 +1,28 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Serialization.UnitTests +{ + public enum Test + { + Zero, + One + } + + [TestClass] + public class SerializerUnitTests + { + [TestMethod] + public void Serializes_Deserializes_Array_Of_EnumValues() + { + //Arrange + Test[] testArray = new Test[] { Test.One, Test.Zero }; + + //Act + byte[] serializedTest = SilverlightSerializer.Serialize(testArray); + Test[] deserializedArray = (Test[])SilverlightSerializer.Deserialize(serializedTest); + + //Assert + CollectionAssert.AreEqual(testArray, deserializedArray); + } + } +} diff --git a/Serialization.sln b/Serialization.sln index 227c2ce..f749ab7 100644 --- a/Serialization.sln +++ b/Serialization.sln @@ -1,61 +1,79 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.SL", "Serialization.SL\Serialization.SL.csproj", "{19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.WP7", "Serialization.WP7\Serialization.WP7.csproj", "{12B1F4A1-3868-411F-B999-B08B312263E9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5D4FFF36-986E-4E8D-B3AF-16AA9D719A31}" - ProjectSection(SolutionItems) = preProject - Build.cmd = Build.cmd - license.txt = license.txt - README.txt = README.txt - Build\SilverlightSerializer.NuSpec = Build\SilverlightSerializer.NuSpec - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization", "Serialization\Serialization.csproj", "{41CCE682-1AA5-449C-8D91-5919E36A93A5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - alchemator|Any CPU = alchemator|Any CPU - Analytics|Any CPU = Analytics|Any CPU - CampaignUI|Any CPU = CampaignUI|Any CPU - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.alchemator|Any CPU.ActiveCfg = alchemator|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.alchemator|Any CPU.Build.0 = alchemator|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Analytics|Any CPU.ActiveCfg = Analytics|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Analytics|Any CPU.Build.0 = Analytics|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.CampaignUI|Any CPU.ActiveCfg = CampaignUI|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.CampaignUI|Any CPU.Build.0 = CampaignUI|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Release|Any CPU.Build.0 = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.alchemator|Any CPU.ActiveCfg = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.alchemator|Any CPU.Build.0 = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Analytics|Any CPU.ActiveCfg = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Analytics|Any CPU.Build.0 = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.CampaignUI|Any CPU.ActiveCfg = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.CampaignUI|Any CPU.Build.0 = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {12B1F4A1-3868-411F-B999-B08B312263E9}.Release|Any CPU.Build.0 = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.alchemator|Any CPU.ActiveCfg = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.alchemator|Any CPU.Build.0 = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Analytics|Any CPU.ActiveCfg = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Analytics|Any CPU.Build.0 = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.CampaignUI|Any CPU.ActiveCfg = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.CampaignUI|Any CPU.Build.0 = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.SL", "Serialization.SL\Serialization.SL.csproj", "{19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.WP7", "Serialization.WP7\Serialization.WP7.csproj", "{12B1F4A1-3868-411F-B999-B08B312263E9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5D4FFF36-986E-4E8D-B3AF-16AA9D719A31}" + ProjectSection(SolutionItems) = preProject + Build.cmd = Build.cmd + license.txt = license.txt + Local.testsettings = Local.testsettings + README.txt = README.txt + Serialization.vsmdi = Serialization.vsmdi + Build\SilverlightSerializer.NuSpec = Build\SilverlightSerializer.NuSpec + TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization", "Serialization\Serialization.csproj", "{41CCE682-1AA5-449C-8D91-5919E36A93A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serialization.UnitTests", "Serialization.UnitTests\Serialization.UnitTests.csproj", "{E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}" +EndProject +Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = Serialization.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + alchemator|Any CPU = alchemator|Any CPU + Analytics|Any CPU = Analytics|Any CPU + CampaignUI|Any CPU = CampaignUI|Any CPU + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.alchemator|Any CPU.ActiveCfg = alchemator|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.alchemator|Any CPU.Build.0 = alchemator|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Analytics|Any CPU.ActiveCfg = Analytics|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Analytics|Any CPU.Build.0 = Analytics|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.CampaignUI|Any CPU.ActiveCfg = CampaignUI|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.CampaignUI|Any CPU.Build.0 = CampaignUI|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {19F5AB5B-439F-41CA-B0C1-C17DCE24BBED}.Release|Any CPU.Build.0 = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.alchemator|Any CPU.ActiveCfg = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.alchemator|Any CPU.Build.0 = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Analytics|Any CPU.ActiveCfg = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Analytics|Any CPU.Build.0 = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.CampaignUI|Any CPU.ActiveCfg = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.CampaignUI|Any CPU.Build.0 = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12B1F4A1-3868-411F-B999-B08B312263E9}.Release|Any CPU.Build.0 = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.alchemator|Any CPU.ActiveCfg = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.alchemator|Any CPU.Build.0 = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Analytics|Any CPU.ActiveCfg = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Analytics|Any CPU.Build.0 = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.CampaignUI|Any CPU.ActiveCfg = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.CampaignUI|Any CPU.Build.0 = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41CCE682-1AA5-449C-8D91-5919E36A93A5}.Release|Any CPU.Build.0 = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.alchemator|Any CPU.ActiveCfg = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.alchemator|Any CPU.Build.0 = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Analytics|Any CPU.ActiveCfg = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Analytics|Any CPU.Build.0 = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.CampaignUI|Any CPU.ActiveCfg = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.CampaignUI|Any CPU.Build.0 = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E6DE2DC4-00D7-40A3-B4DD-E801D9606CD9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Serialization.vsmdi b/Serialization.vsmdi new file mode 100644 index 0000000..8bbcc16 --- /dev/null +++ b/Serialization.vsmdi @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TraceAndTestImpact.testsettings b/TraceAndTestImpact.testsettings new file mode 100644 index 0000000..cd87b96 --- /dev/null +++ b/TraceAndTestImpact.testsettings @@ -0,0 +1,9 @@ + + + These are test settings for Trace and Test Impact. + + + + + + \ No newline at end of file