Skip to content

Commit

Permalink
Ported fix for #2706
Browse files Browse the repository at this point in the history
  • Loading branch information
distantcam committed Apr 30, 2015
1 parent aa64ed3 commit 9f67e1e
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@ public MessageWithArray(Guid sagaId, int[] someInts)
SomeInts = someInts;
}
}

[Serializable]
public class MessageWithArrayAndNoDefaultCtor
{
public Guid SagaId { get; set; }
public string[] SomeWords { get; set; }
}
}

[Serializable]
public class MessageWithNullableArray
{
public Guid SagaId { get; set; }
public int?[] SomeInts { get; set; }
}

[TestFixture]
public class SerializingArrayTests
{

[Test]
public void CanDeserializeXmlWithWhitespace()
{
Expand Down Expand Up @@ -71,6 +77,7 @@ public void CanSerializeAndBack()
Assert.AreEqual(1234, result.SomeInts[0]);
Assert.AreEqual(5323, result.SomeInts[1]);
}

[Test]
public void CanSerializeMessageWithNullArray()
{
Expand All @@ -83,6 +90,7 @@ public void CanSerializeMessageWithNullArray()

Assert.IsNull(result.SomeWords);
}

[Test]
public void CanSerializeMessageWithEmptyArray()
{
Expand All @@ -95,5 +103,74 @@ public void CanSerializeMessageWithEmptyArray()

Assert.AreEqual(result.SomeWords, new string[0]);
}

[Test]
public void CanSerializeNullableArrayWithNullString()
{
var message = new MessageWithNullableArray
{
SagaId = Guid.Empty,
SomeInts = new int?[] { null }
};

using (var stream = new MemoryStream())
{
SerializerFactory.Create<MessageWithNullableArray>().Serialize(message, stream);
stream.Position = 0;
var reader = new StreamReader(stream);
var xml = reader.ReadToEnd().Replace("\r\n", "\n").Replace("\n", "\r\n");

Assert.AreEqual(@"<?xml version=""1.0"" ?>
<MessageWithNullableArray xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://tempuri.net/NServiceBus.Serializers.XML.Test"">
<SagaId>00000000-0000-0000-0000-000000000000</SagaId>
<SomeInts>
<NullableOfInt32>
null</NullableOfInt32>
</SomeInts>
</MessageWithNullableArray>
", xml);
}
}

[Test]
public void CanDeserializeNullableArrayWithValueSetToNullString()
{
var xml = @"<?xml version=""1.0"" ?>
<MessageWithNullableArray xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://tempuri.net/NServiceBus.Serializers.XML.Test"">
<SagaId>00000000-0000-0000-0000-000000000000</SagaId>
<SomeInts>
<NullableOfInt32>null</NullableOfInt32>
</SomeInts>
</MessageWithNullableArray>
";
var data = Encoding.UTF8.GetBytes(xml);

using (var stream = new MemoryStream(data))
{
var msgArray = SerializerFactory.Create<MessageWithNullableArray>().Deserialize(stream, new[] { typeof(MessageWithNullableArray) });
var result = (MessageWithNullableArray)msgArray[0];

Assert.AreEqual(null, result.SomeInts[0]);
}
}

[Test]
public void CanSerializeMessageWithNullableArray()
{
// Issue https://github.com/Particular/NServiceBus/issues/2706

var message = new MessageWithNullableArray
{
SomeInts = new int?[] { null, 1, null, 3, null }
};

var result = ExecuteSerializer.ForMessage<MessageWithNullableArray>(message);

Assert.IsNull(result.SomeInts[0]);
Assert.AreEqual(1, result.SomeInts[1]);
Assert.IsNull(result.SomeInts[2]);
Assert.AreEqual(3, result.SomeInts[3]);
Assert.IsNull(result.SomeInts[4]);
}
}
}
7 changes: 3 additions & 4 deletions src/NServiceBus.Core/Serializers/XML/Deserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ Type InferNodeType(XmlNode node, object parent)
return mappedType;
}


logger.Debug("Could not load " + typeName + ". Trying base types...");
foreach (var baseType in messageBaseTypes)
{
Expand All @@ -243,7 +242,7 @@ Type InferNodeType(XmlNode node, object parent)
logger.Debug("Trying to deserialize message to " + baseType.FullName);
return baseType;
}
// ReSharper disable once EmptyGeneralCatchClause
// ReSharper disable once EmptyGeneralCatchClause
catch
{
// intentionally swallow exception
Expand All @@ -255,7 +254,7 @@ Type InferNodeType(XmlNode node, object parent)

object GetObjectOfTypeFromNode(Type t, XmlNode node)
{
if (t.IsSimpleType() || t == typeof(Uri))
if (t.IsSimpleType() || t == typeof(Uri) || t.IsNullableType())
{
return GetPropertyValue(t, node);
}
Expand Down Expand Up @@ -340,7 +339,7 @@ object GetPropertyValue(Type type, XmlNode n)
var nullableType = typeof(Nullable<>).MakeGenericType(args);
if (type == nullableType)
{
if (text.ToLower() == "null")
if (text.Trim().ToLower() == "null")
{
return null;
}
Expand Down
67 changes: 41 additions & 26 deletions src/NServiceBus.Core/Serializers/XML/Serializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,77 +74,81 @@ StringBuilder SerializeMessage(object message)

static string FormatAsString(object value)
{
if (value == null)
{
return "null";
}
if (value is bool)
{
return XmlConvert.ToString((bool) value);
return XmlConvert.ToString((bool)value);
}
if (value is byte)
{
return XmlConvert.ToString((byte) value);
return XmlConvert.ToString((byte)value);
}
if (value is char)
{
return Escape((char) value);
return Escape((char)value);
}
if (value is double)
{
return XmlConvert.ToString((double) value);
return XmlConvert.ToString((double)value);
}
if (value is ulong)
{
return XmlConvert.ToString((ulong) value);
return XmlConvert.ToString((ulong)value);
}
if (value is uint)
{
return XmlConvert.ToString((uint) value);
return XmlConvert.ToString((uint)value);
}
if (value is ushort)
{
return XmlConvert.ToString((ushort) value);
return XmlConvert.ToString((ushort)value);
}
if (value is long)
{
return XmlConvert.ToString((long) value);
return XmlConvert.ToString((long)value);
}
if (value is int)
{
return XmlConvert.ToString((int) value);
return XmlConvert.ToString((int)value);
}
if (value is short)
{
return XmlConvert.ToString((short) value);
return XmlConvert.ToString((short)value);
}
if (value is sbyte)
{
return XmlConvert.ToString((sbyte) value);
return XmlConvert.ToString((sbyte)value);
}
if (value is decimal)
{
return XmlConvert.ToString((decimal) value);
return XmlConvert.ToString((decimal)value);
}
if (value is float)
{
return XmlConvert.ToString((float) value);
return XmlConvert.ToString((float)value);
}
if (value is Guid)
{
return XmlConvert.ToString((Guid) value);
return XmlConvert.ToString((Guid)value);
}
if (value is DateTime)
{
return XmlConvert.ToString((DateTime) value, XmlDateTimeSerializationMode.RoundtripKind);
return XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind);
}
if (value is DateTimeOffset)
{
return XmlConvert.ToString((DateTimeOffset) value);
return XmlConvert.ToString((DateTimeOffset)value);
}
if (value is TimeSpan)
{
return XmlConvert.ToString((TimeSpan) value);
return XmlConvert.ToString((TimeSpan)value);
}
if (value is string)
{
return Escape(value as string);
return Escape((string)value);
}

return Escape(value.ToString());
Expand All @@ -166,15 +170,19 @@ static string Escape(char c)
case '<':
ss = "&lt;";
break;

case '>':
ss = "&gt;";
break;

case '"':
ss = "&quot;";
break;

case '\'':
ss = "&apos;";
break;

case '&':
ss = "&amp;";
break;
Expand All @@ -186,7 +194,7 @@ static string Escape(char c)
}
else
{
return String.Format("&#x{0:X};", (int) c);
return String.Format("&#x{0:X};", (int)c);
}

//Should not get here but just in case!
Expand Down Expand Up @@ -218,15 +226,19 @@ static string Escape(string stringToEscape)
case '<':
ss = "&lt;";
break;

case '>':
ss = "&gt;";
break;

case '"':
ss = "&quot;";
break;

case '\'':
ss = "&apos;";
break;

case '&':
ss = "&amp;";
break;
Expand Down Expand Up @@ -257,7 +269,7 @@ static string Escape(string stringToEscape)
builder.Append(stringToEscape, startIndex, i - startIndex);
}
startIndex = i + 1;
builder.AppendFormat("&#x{0:X};", (int) c);
builder.AppendFormat("&#x{0:X};", (int)c);
}
}

Expand Down Expand Up @@ -318,7 +330,7 @@ void WriteObject(string name, Type type, object value, StringBuilder builder, bo
{
var element = name;

if (type == typeof(object) && (value.GetType().IsSimpleType()))
if (type == typeof(object) && value.GetType().IsSimpleType())
{
if (!namespacesToAdd.Contains(value.GetType()))
{
Expand All @@ -332,7 +344,6 @@ void WriteObject(string name, Type type, object value, StringBuilder builder, bo
return;
}


if (useNS)
{
var @namespace = InitializeNamespaces(value);
Expand All @@ -353,6 +364,11 @@ void Write(StringBuilder builder, Type t, object obj)
{
if (obj == null)
{
// For null entries in a nullable array
// See https://github.com/Particular/NServiceBus/issues/2706
if (t.IsNullableType())
builder.Append("null");

return;
}

Expand Down Expand Up @@ -402,7 +418,7 @@ void WriteEntry(string name, Type type, object value, StringBuilder builder)

if (typeof(XContainer).IsAssignableFrom(type))
{
var container = (XContainer) value;
var container = (XContainer)value;
if (SkipWrappingRawXml)
{
builder.AppendFormat("{0}\n", container);
Expand All @@ -427,7 +443,7 @@ void WriteEntry(string name, Type type, object value, StringBuilder builder)

if (type == typeof(byte[]))
{
var base64String = Convert.ToBase64String((byte[]) value);
var base64String = Convert.ToBase64String((byte[])value);
builder.Append(base64String);
}
else
Expand Down Expand Up @@ -459,8 +475,7 @@ void WriteEntry(string name, Type type, object value, StringBuilder builder)
}
}


foreach (var obj in ((IEnumerable) value))
foreach (var obj in ((IEnumerable)value))
{
if (obj != null && obj.GetType().IsSimpleType())
{
Expand Down
10 changes: 10 additions & 0 deletions src/NServiceBus.Core/Utils/Reflection/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ public static bool IsSimpleType(this Type type)
type.IsEnum);
}

public static bool IsNullableType(this Type type)
{
var args = type.GetGenericArguments();
if (args.Length == 1 && args[0].IsValueType)
{
return type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
return false;
}

/// <summary>
/// Takes the name of the given type and makes it friendly for serialization
/// by removing problematic characters.
Expand Down

0 comments on commit 9f67e1e

Please sign in to comment.