Index: Core/Common/src/Core.Common.Utils/Core.Common.Utils.csproj =================================================================== diff -u -r96c96a5f55735cb1d019a5fd8677200e2079284d -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Core/Common/src/Core.Common.Utils/Core.Common.Utils.csproj (.../Core.Common.Utils.csproj) (revision 96c96a5f55735cb1d019a5fd8677200e2079284d) +++ Core/Common/src/Core.Common.Utils/Core.Common.Utils.csproj (.../Core.Common.Utils.csproj) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -103,6 +103,7 @@ + True True Index: Core/Common/src/Core.Common.Utils/EnumTypeConverter.cs =================================================================== diff -u -rccf22c570f610fc47e18f8e92afc6aab2ee6c896 -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Core/Common/src/Core.Common.Utils/EnumTypeConverter.cs (.../EnumTypeConverter.cs) (revision ccf22c570f610fc47e18f8e92afc6aab2ee6c896) +++ Core/Common/src/Core.Common.Utils/EnumTypeConverter.cs (.../EnumTypeConverter.cs) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -60,9 +60,7 @@ return base.ConvertTo(context, culture, value, destinationType); } - var fieldInfo = EnumType.IsGenericType && EnumType.GetGenericTypeDefinition() == typeof(Nullable<>) ? - EnumType.GetGenericArguments()[0].GetField(value.ToString()) : - EnumType.GetField(value.ToString()); + var fieldInfo = EnumType.GetField(value.ToString()); return GetDisplayName(fieldInfo); } Index: Core/Common/src/Core.Common.Utils/NullableEnumTypeConverter.cs =================================================================== diff -u --- Core/Common/src/Core.Common.Utils/NullableEnumTypeConverter.cs (revision 0) +++ Core/Common/src/Core.Common.Utils/NullableEnumTypeConverter.cs (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -0,0 +1,103 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Reflection; +using Core.Common.Utils.Attributes; + +namespace Core.Common.Utils +{ + /// + /// A type converter to convert nullable Enum objects to and from various other representations. + /// + public class NullableEnumTypeConverter : NullableConverter + { + /// + /// Initializes a new instance of the class for the given a nullable Enum . + /// + /// This class is designed such that it looks for on each Enum value. + /// A that represents the type of enumeration to associate with this enumeration converter. + /// Thrown when is not a nullable type. + public NullableEnumTypeConverter(Type type) : base(type) {} + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value == null) + { + throw new NotSupportedException("NullableEnumTypeConverter cannot convert from (null)."); + } + var valueString = value as string; + if (valueString != null) + { + foreach (var fieldInfo in UnderlyingType.GetFields().Where(fieldInfo => valueString == GetDisplayName(fieldInfo))) + { + return Enum.Parse(UnderlyingType, fieldInfo.Name); + } + } + return base.ConvertFrom(context, culture, value); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (destinationType != typeof(string) || value == null) + { + return base.ConvertTo(context, culture, value, destinationType); + } + + var fieldInfo = UnderlyingType.GetField(value.ToString()); + return GetDisplayName(fieldInfo); + } + + /// + /// Gets a collection of standard values for the data type this type converted is designed for. + /// + /// An that provides a format + /// context that can be used to extract additional information about the environment + /// from which this converter is invoked. This parameter or properties of this parameter can be null. + /// A that holds a standard + /// set of valid values, or null if the data type does not support a standard set of values. + /// Does not add a value for null to the . + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) + { + if (UnderlyingTypeConverter == null) + { + return base.GetStandardValues(context); + } + + StandardValuesCollection values = UnderlyingTypeConverter.GetStandardValues(context); + if (GetStandardValuesSupported(context) && values != null) + { + return new StandardValuesCollection(values); + } + + return base.GetStandardValues(context); + } + + private static string GetDisplayName(MemberInfo memberInfo) + { + var resourcesDisplayNameAttribute = (ResourcesDisplayNameAttribute) Attribute.GetCustomAttribute(memberInfo, typeof(ResourcesDisplayNameAttribute)); + return (resourcesDisplayNameAttribute != null) ? resourcesDisplayNameAttribute.DisplayName : null; + } + } +} \ No newline at end of file Index: Core/Common/test/Core.Common.Utils.Test/Core.Common.Utils.Test.csproj =================================================================== diff -u -r0efb28b7f5a708daa1cf9e8aeba6b8f84a3ebaf5 -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Core/Common/test/Core.Common.Utils.Test/Core.Common.Utils.Test.csproj (.../Core.Common.Utils.Test.csproj) (revision 0efb28b7f5a708daa1cf9e8aeba6b8f84a3ebaf5) +++ Core/Common/test/Core.Common.Utils.Test/Core.Common.Utils.Test.csproj (.../Core.Common.Utils.Test.csproj) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -64,6 +64,10 @@ True + + ..\..\..\..\packages\RhinoMocks.3.6.1\lib\net\Rhino.Mocks.dll + True + 3.5 @@ -92,6 +96,7 @@ + True Index: Core/Common/test/Core.Common.Utils.Test/EnumTypeConverterTest.cs =================================================================== diff -u -rccf22c570f610fc47e18f8e92afc6aab2ee6c896 -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Core/Common/test/Core.Common.Utils.Test/EnumTypeConverterTest.cs (.../EnumTypeConverterTest.cs) (revision ccf22c570f610fc47e18f8e92afc6aab2ee6c896) +++ Core/Common/test/Core.Common.Utils.Test/EnumTypeConverterTest.cs (.../EnumTypeConverterTest.cs) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -37,7 +37,7 @@ var converter = new EnumTypeConverter(typeof(object)); // Assert - Assert.IsInstanceOf(converter); + Assert.IsInstanceOf(converter); } [Test] @@ -139,36 +139,6 @@ } [Test] - public void ConvertTo_FromNullableToString_ReturnsExpectedEnumDisplayName() - { - // Setup - SimpleEnum? enumValue = SimpleEnum.FirstValue; - var converter = new EnumTypeConverter(typeof(SimpleEnum?)); - - // Call - var result = converter.ConvertTo(enumValue, typeof(string)); - - // Assert - const string expectedText = ""; - Assert.AreEqual(expectedText, result); - } - - [Test] - public void ConvertTo_FromNullableWithNullValue_ReturnsEmptyDisplayName() - { - // Setup - SimpleEnum? enumValue = null; - var converter = new EnumTypeConverter(typeof(SimpleEnum?)); - - // Call - var result = converter.ConvertTo(enumValue, typeof(string)); - - // Assert - string expectedText = string.Empty; - Assert.AreEqual(expectedText, result); - } - - [Test] public void CanConvertFrom_SourceTypeIsInvalid_ReturnsFalse() { // Setup Index: Core/Common/test/Core.Common.Utils.Test/NullableEnumTypeConverterTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.Utils.Test/NullableEnumTypeConverterTest.cs (revision 0) +++ Core/Common/test/Core.Common.Utils.Test/NullableEnumTypeConverterTest.cs (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -0,0 +1,261 @@ +// Copyright (C) Stichting Deltares 2016. All rights reserved. +// +// This file is part of Ringtoets. +// +// Ringtoets is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.ComponentModel; +using Core.Common.Utils.Attributes; +using Core.Common.Utils.Test.Properties; +using NUnit.Framework; +using Rhino.Mocks; + +namespace Core.Common.Utils.Test +{ + [TestFixture] + public class NullableEnumTypeConverterTest + { + [Test] + public void DefaultConstructor_ExpectedValues() + { + // Call + var nullableType = typeof(SimpleEnum?); + var converter = new NullableEnumTypeConverter(nullableType); + + // Assert + Assert.IsInstanceOf(converter); + Assert.AreEqual(nullableType, converter.NullableType); + Assert.AreEqual(typeof(SimpleEnum), converter.UnderlyingType); + Assert.AreEqual(typeof(EnumConverter), converter.UnderlyingTypeConverter.GetType()); + } + + [Test] + public void CanConvertTo_DestinationTypeIsInvalid_ReturnsFalse() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var canConvert = converter.CanConvertTo(typeof(NotSupportedType)); + + // Assert + Assert.IsFalse(canConvert); + } + + [Test] + public void CanConvertTo_DestinationTypeIsString_ReturnsTrue() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var canConvert = converter.CanConvertTo(typeof(string)); + + // Assert + Assert.IsTrue(canConvert); + } + + [Test] + public void ConvertTo_ValueIsOfInvalidType_ThrowsNotSupportedException() + { + // Setup + var notSupportedValue = new NotSupportedType(); + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TestDelegate test = () => converter.ConvertTo(notSupportedValue, typeof(SimpleEnum)); + + // Assert + Assert.Throws(test); + } + + [Test] + public void ConvertTo_ValueIsNull_DoesNotThrowException() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + object result = new object(); + TestDelegate test = () => result = converter.ConvertTo(null, typeof(string)); + + // Assert + Assert.DoesNotThrow(test); + Assert.AreEqual(string.Empty, result); + } + + [Test] + public void ConvertTo_DestinationTypeIsNull_ThrowsArgumentNullException() + { + // Setup + const SimpleEnum enumValue = SimpleEnum.FirstValue; + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TestDelegate test = () => converter.ConvertTo(enumValue, null); + + // Assert + Assert.Throws(test); + } + + [Test] + public void ConvertTo_DestinationTypeIsInvalid_ThrowsNotSupportedException() + { + // Setup + const SimpleEnum enumValue = SimpleEnum.FirstValue; + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TestDelegate test = () => converter.ConvertTo(enumValue, typeof(NotSupportedType)); + + // Assert + Assert.Throws(test); + } + + [Test] + public void ConvertTo_DestinationTypeIsString_ReturnsExpectedEnumDisplayName() + { + // Setup + const SimpleEnum enumValue = SimpleEnum.FirstValue; + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var result = converter.ConvertTo(enumValue, typeof(string)); + + // Assert + const string expectedText = ""; + Assert.AreEqual(expectedText, result); + } + + [Test] + public void CanConvertFrom_SourceTypeIsInvalid_ReturnsFalse() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var canConvert = converter.CanConvertFrom(typeof(NotSupportedType)); + + // Assert + Assert.IsFalse(canConvert); + } + + [Test] + public void CanConvertFrom_SourceTypeIsString_ReturnsTrue() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var canConvert = converter.CanConvertFrom(typeof(string)); + + // Assert + Assert.IsTrue(canConvert); + } + + [Test] + public void ConvertFrom_ValueIsOfInvalidType_ThrowsNotSupportedException() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TestDelegate test = () => converter.ConvertFrom(typeof(NotSupportedType)); + + // Assert + Assert.Throws(test); + } + + [Test] + public void ConvertFrom_ValueIsNull_ThrowsNotSupportedException() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TestDelegate test = () => converter.ConvertFrom(null); + + // Assert + Assert.Throws(test); + } + + [Test] + public void ConvertFrom_ValueIsString_ReturnsExpectedEnum() + { + // Setup + const string second = ""; + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + var result = converter.ConvertFrom(second); + + // Assert + var expectedEnumValue = SimpleEnum.SecondValue; + Assert.AreEqual(expectedEnumValue, result); + } + + [Test] + public void GetStandardValues_ITypeDescriptorContextIsNull_ReturnEnumValues() + { + // Setup + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TypeConverter.StandardValuesCollection result = converter.GetStandardValues(null); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(2, result.Count); + Assert.AreEqual(SimpleEnum.FirstValue, result[0]); + Assert.AreEqual(SimpleEnum.SecondValue, result[1]); + } + + [Test] + public void GetStandardValues_ITypeDescriptorContext_ReturnEnumValues() + { + // Setup + var mockRepository = new MockRepository(); + var typeDescriptorContextStub = mockRepository.Stub(); + mockRepository.ReplayAll(); + + var converter = new NullableEnumTypeConverter(typeof(SimpleEnum?)); + + // Call + TypeConverter.StandardValuesCollection result = converter.GetStandardValues(typeDescriptorContextStub); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(2, result.Count); + Assert.AreEqual(SimpleEnum.FirstValue, result[0]); + Assert.AreEqual(SimpleEnum.SecondValue, result[1]); + mockRepository.VerifyAll(); + } + + private enum SimpleEnum + { + [ResourcesDisplayName(typeof(Resources), "SimpleEnum_FirstValue_DisplayName")] + FirstValue, + + [ResourcesDisplayName(typeof(Resources), "SimpleEnum_SecondValue_DisplayName")] + SecondValue + } + + private class NotSupportedType {} + } +} \ No newline at end of file Index: Core/Common/test/Core.Common.Utils.Test/packages.config =================================================================== diff -u -rfea3ed82dfb6dfcad535eef16efcbaa9c01564ed -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Core/Common/test/Core.Common.Utils.Test/packages.config (.../packages.config) (revision fea3ed82dfb6dfcad535eef16efcbaa9c01564ed) +++ Core/Common/test/Core.Common.Utils.Test/packages.config (.../packages.config) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -23,4 +23,5 @@ --> + \ No newline at end of file Index: Ringtoets/Common/src/Ringtoets.Common.Forms/PropertyClasses/UseBreakWaterProperties.cs =================================================================== diff -u -rccf22c570f610fc47e18f8e92afc6aab2ee6c896 -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Ringtoets/Common/src/Ringtoets.Common.Forms/PropertyClasses/UseBreakWaterProperties.cs (.../UseBreakWaterProperties.cs) (revision ccf22c570f610fc47e18f8e92afc6aab2ee6c896) +++ Ringtoets/Common/src/Ringtoets.Common.Forms/PropertyClasses/UseBreakWaterProperties.cs (.../UseBreakWaterProperties.cs) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -72,7 +72,7 @@ [PropertyOrder(breakWaterTypePropertyIndex)] [ResourcesDisplayName(typeof(Resources), "BreakWaterType_DisplayName")] [ResourcesDescription(typeof(Resources), "BreakWaterType_Description")] - [TypeConverter(typeof(EnumTypeConverter))] + [TypeConverter(typeof(NullableEnumTypeConverter))] public BreakWaterType? BreakWaterType { get Index: Ringtoets/Common/test/Ringtoets.Common.Forms.Test/PropertyClasses/UseBreakWaterPropertiesTest.cs =================================================================== diff -u -rccf22c570f610fc47e18f8e92afc6aab2ee6c896 -r780ed8dd33ce62d2e6e939811ca331ba1feed85f --- Ringtoets/Common/test/Ringtoets.Common.Forms.Test/PropertyClasses/UseBreakWaterPropertiesTest.cs (.../UseBreakWaterPropertiesTest.cs) (revision ccf22c570f610fc47e18f8e92afc6aab2ee6c896) +++ Ringtoets/Common/test/Ringtoets.Common.Forms.Test/PropertyClasses/UseBreakWaterPropertiesTest.cs (.../UseBreakWaterPropertiesTest.cs) (revision 780ed8dd33ce62d2e6e939811ca331ba1feed85f) @@ -24,10 +24,12 @@ using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Gui.PropertyBag; +using Core.Common.Utils; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.DikeProfiles; using Ringtoets.Common.Forms.PropertyClasses; +using Ringtoets.Common.Forms.TypeConverters; namespace Ringtoets.Common.Forms.Test.PropertyClasses { @@ -124,12 +126,14 @@ PropertyDescriptor breakWaterTypeProperty = dynamicProperties[1]; Assert.IsNotNull(breakWaterTypeProperty); Assert.AreEqual(!useBreakWaterEnabled || !useBreakWater, breakWaterTypeProperty.IsReadOnly); + Assert.IsInstanceOf(breakWaterTypeProperty.Converter); Assert.AreEqual("Type", breakWaterTypeProperty.DisplayName); Assert.AreEqual("Het type van de dam.", breakWaterTypeProperty.Description); PropertyDescriptor breakWaterHeightProperty = dynamicProperties[2]; Assert.IsNotNull(breakWaterHeightProperty); Assert.AreEqual(!useBreakWaterEnabled || !useBreakWater, breakWaterHeightProperty.IsReadOnly); + Assert.IsInstanceOf(breakWaterHeightProperty.Converter); Assert.AreEqual("Hoogte [m+NAP]", breakWaterHeightProperty.DisplayName); Assert.AreEqual("De hoogte van de dam.", breakWaterHeightProperty.Description); }