From 5006115b2dbdccb801ce3657c726e2196433b405 Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 2 Nov 2013 15:20:04 +1100 Subject: [PATCH] Fixes object extensions and tests Conflicts: src/Umbraco.Core/ObjectExtensions.cs src/Umbraco.Tests/ObjectExtensionsTests.cs --- src/Umbraco.Core/ObjectExtensions.cs | 131 +++++++++++---------- src/Umbraco.Tests/ObjectExtensionsTests.cs | 16 +++ 2 files changed, 86 insertions(+), 61 deletions(-) diff --git a/src/Umbraco.Core/ObjectExtensions.cs b/src/Umbraco.Core/ObjectExtensions.cs index 007b347aeb..5e285d341d 100644 --- a/src/Umbraco.Core/ObjectExtensions.cs +++ b/src/Umbraco.Core/ObjectExtensions.cs @@ -88,8 +88,17 @@ namespace Umbraco.Core // if we've got a nullable of something, we try to convert directly to that thing. if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>)) { + var underlyingType = Nullable.GetUnderlyingType(destinationType); + + //special case for empty strings for bools/dates which should return null if an empty string + var asString = input as string; + if (asString != null && string.IsNullOrEmpty(asString) && (underlyingType == typeof(DateTime) || underlyingType == typeof(bool))) + { + return Attempt.Succeed(null); + } + // recursively call into myself with the inner (not-nullable) type and handle the outcome - var nonNullable = input.TryConvertTo(Nullable.GetUnderlyingType(destinationType)); + var nonNullable = input.TryConvertTo(underlyingType); // and if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception if (nonNullable.Success) @@ -193,78 +202,78 @@ namespace Umbraco.Core if (destinationType == typeof(string)) return Attempt.Succeed(input); - if (input == null || input.Length == 0) + if (string.IsNullOrEmpty(input)) { if (destinationType == typeof(Boolean)) return Attempt.Succeed(false); // special case for booleans, null/empty == false - else if (destinationType == typeof(DateTime)) - return Attempt.Succeed(false); + if (destinationType == typeof(DateTime)) + return Attempt.Succeed(DateTime.MinValue); } // we have a non-empty string, look for type conversions in the expected order of frequency of use... if (destinationType.IsPrimitive) { - if (destinationType == typeof(Int32)) + if (destinationType == typeof(Int32)) { Int32 value; return Int32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); } - else if (destinationType == typeof(Int64)) - { - Int64 value; - return Int64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Boolean)) - { - Boolean value; - if (Boolean.TryParse(input, out value)) - return Attempt.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try - } - else if (destinationType == typeof(Int16)) - { - Int16 value; - return Int16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Double)) - { - Double value; - return Double.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Single)) - { - Single value; - return Single.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Char)) - { - Char value; - return Char.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(Byte)) - { - Byte value; - return Byte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(SByte)) - { - SByte value; - return SByte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt32)) - { - UInt32 value; - return UInt32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt16)) - { - UInt16 value; - return UInt16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } - else if (destinationType == typeof(UInt64)) - { - UInt64 value; - return UInt64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); - } + if (destinationType == typeof(Int64)) + { + Int64 value; + return Int64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + if (destinationType == typeof(Boolean)) + { + Boolean value; + if (Boolean.TryParse(input, out value)) + return Attempt.Succeed(value); // don't declare failure so the CustomBooleanTypeConverter can try + } + else if (destinationType == typeof(Int16)) + { + Int16 value; + return Int16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Double)) + { + Double value; + return Double.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Single)) + { + Single value; + return Single.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Char)) + { + Char value; + return Char.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(Byte)) + { + Byte value; + return Byte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(SByte)) + { + SByte value; + return SByte.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt32)) + { + UInt32 value; + return UInt32.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt16)) + { + UInt16 value; + return UInt16.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } + else if (destinationType == typeof(UInt64)) + { + UInt64 value; + return UInt64.TryParse(input, out value) ? Attempt.Succeed(value) : Attempt.Fail(); + } } else if (destinationType == typeof(Guid)) { diff --git a/src/Umbraco.Tests/ObjectExtensionsTests.cs b/src/Umbraco.Tests/ObjectExtensionsTests.cs index aa433e40ec..f3aab4772c 100644 --- a/src/Umbraco.Tests/ObjectExtensionsTests.cs +++ b/src/Umbraco.Tests/ObjectExtensionsTests.cs @@ -116,6 +116,22 @@ namespace Umbraco.Tests } } + [Test] + public virtual void CanConvertBlankStringToNullDateTime() + { + var result = "".TryConvertTo(); + Assert.IsTrue(result.Success); + Assert.IsNull(result.Result); + } + + [Test] + public virtual void CanConvertBlankStringToNullBool() + { + var result = "".TryConvertTo(); + Assert.IsTrue(result.Success); + Assert.IsNull(result.Result); + } + [Test] public virtual void CanConvertBlankStringToDateTime() {