diff --git a/src/Serialization/AmqpSerializer.cs b/src/Serialization/AmqpSerializer.cs index 1c24669f..76e69d9c 100644 --- a/src/Serialization/AmqpSerializer.cs +++ b/src/Serialization/AmqpSerializer.cs @@ -407,6 +407,12 @@ SerializableType CompileCollectionTypes(Type type) MethodAccessor addAccess = null; Type itemType = null; + if (type.IsArray) + { + // array of custom types. encode it as list + return SerializableType.CreateArrayType(this, type, type.GetElementType()); + } + foreach (Type it in type.GetInterfaces()) { if (it.IsGenericType()) diff --git a/src/Serialization/SerializableType.cs b/src/Serialization/SerializableType.cs index 65b1e88a..942ebdad 100644 --- a/src/Serialization/SerializableType.cs +++ b/src/Serialization/SerializableType.cs @@ -83,6 +83,11 @@ public static SerializableType CreateAmqpSerializableType(AmqpSerializer seriali return new AmqpSerializableType(serializer, type); } + public static SerializableType CreateArrayType(AmqpSerializer serializer, Type type, Type itemType) + { + return new ArrayType(serializer, type, itemType); + } + public static SerializableType CreateGenericListType( AmqpSerializer serializer, Type type, @@ -366,6 +371,38 @@ protected static void ReadSizeAndCount(ByteBuffer buffer, byte formatCode, out i } } + sealed class ArrayType : SerializableType + { + readonly Type itemType; + readonly SerializableType listType; + + public ArrayType(AmqpSerializer serializer, Type type, Type itemType) + : base(serializer, type) + { + this.itemType = itemType; + this.listType = serializer.GetType(typeof(List<>).MakeGenericType(itemType)); + } + + public override void WriteObject(ByteBuffer buffer, object graph) + { + this.listType.WriteObject(buffer, graph); + } + + public override object ReadObject(ByteBuffer buffer) + { + object value = this.listType.ReadObject(buffer); + if (value != null) + { + ICollection list = (ICollection)value; + Array array = Array.CreateInstance(this.itemType, list.Count); + list.CopyTo(array, 0); + value = array; + } + + return value; + } + } + sealed class GenericListType : CollectionType { readonly SerializableType itemType; diff --git a/src/Types/Encoder.cs b/src/Types/Encoder.cs index ec85c6a2..923e5725 100644 --- a/src/Types/Encoder.cs +++ b/src/Types/Encoder.cs @@ -292,7 +292,7 @@ internal static bool TryGetCodec(Type type, out Encode encoder, out Decode decod Serializer codec = (Serializer)codecByType[type]; if (codec == null) { - if (type.IsArray) + if (type.IsArray && codecByType[type.GetElementType()] != null) { codec = serializers[20]; } diff --git a/test/Common/AmqpSerializerTests.cs b/test/Common/AmqpSerializerTests.cs index 39a5a7ef..0f9ffdcb 100644 --- a/test/Common/AmqpSerializerTests.cs +++ b/test/Common/AmqpSerializerTests.cs @@ -537,6 +537,36 @@ public void AmqpSerializerMessageBodyTest() (x, y) => CollectionAssert.AreEqual(x, y)); } + [TestMethod] + public void AmqpSerializerCustomTypeArrayTest() + { + Person[] value = new Person[] + { + new Student("Tom") { Age = 13 }, + new Teacher("Bob") { Sallary = 1234 }, + null, + new Student("Al") { Age = 12 }, + }; + + ByteBuffer b = new ByteBuffer(512, true); + AmqpSerializer.Serialize(b, value); + Person[] o = AmqpSerializer.Deserialize(b); + Assert.AreEqual(value.Length, o.Length); + for (int i = 0; i < value.Length; i++) + { + if (value[i] == null) + { + Assert.IsTrue(o[i] == null); + } + else + { + Assert.AreEqual(value[i].GetType(), o[i].GetType()); + Assert.AreEqual(value[i].Name, o[i].Name); + Assert.AreEqual(value[i].Age + 1, o[i].Age); + } + } + } + #if !DOTNET [TestMethod] public void MessageSerializationTest()