Permalink
Browse files

Fix for issue #191 Cannot convert enum to nullable int

  • Loading branch information...
1 parent 54cdf53 commit 19f0cb7b2064b7623fc5164729b2fe7be808603b @dvorobiov dvorobiov committed with jbogard Apr 8, 2012
Showing with 180 additions and 117 deletions.
  1. +143 −117 src/AutoMapper/Mappers/EnumMapper.cs
  2. +36 −0 src/UnitTests/Bug/CannotConvertEnumToNullable.cs
  3. +1 −0 src/UnitTests/UnitTests.csproj
@@ -1,118 +1,144 @@
-using System;
-using System.Linq;
-
-namespace AutoMapper.Mappers
-{
- public class EnumMapper : IObjectMapper
- {
- public object Map(ResolutionContext context, IMappingEngineRunner mapper)
- {
- bool toEnum = false;
- Type enumSourceType = TypeHelper.GetEnumerationType(context.SourceType);
- Type enumDestinationType = TypeHelper.GetEnumerationType(context.DestinationType);
-
- if (EnumToStringMapping(context, ref toEnum))
- {
- if (context.SourceValue == null)
- {
- return mapper.CreateObject(context);
- }
-
- if (toEnum)
- {
- var stringValue = context.SourceValue.ToString();
- if (string.IsNullOrEmpty(stringValue))
- {
- return mapper.CreateObject(context);
- }
-
- return Enum.Parse(enumDestinationType, stringValue, true);
- }
- return Enum.GetName(enumSourceType, context.SourceValue);
- }
- if (EnumToEnumMapping(context))
- {
- if (context.SourceValue == null)
- {
- return mapper.CreateObject(context);
- }
-
- if (!Enum.IsDefined(enumSourceType, context.SourceValue))
- {
- return Enum.ToObject(enumDestinationType, context.SourceValue);
- }
-
-#if !SILVERLIGHT
- if (!Enum.GetNames(enumDestinationType).Contains(context.SourceValue.ToString()))
- {
- Type underlyingSourceType = Enum.GetUnderlyingType(enumSourceType);
- var underlyingSourceValue = Convert.ChangeType(context.SourceValue, underlyingSourceType);
-
- return Enum.ToObject(context.DestinationType, underlyingSourceValue);
- }
-#endif
-
- return Enum.Parse(enumDestinationType, Enum.GetName(enumSourceType, context.SourceValue), true);
- }
- if (EnumToUnderlyingTypeMapping(context, ref toEnum))
- {
- if (toEnum)
- {
- return Enum.Parse(enumDestinationType, context.SourceValue.ToString(), true);
- }
- return Convert.ChangeType(context.SourceValue, context.DestinationType, null);
- }
- return null;
- }
-
- public bool IsMatch(ResolutionContext context)
- {
- bool toEnum = false;
- return EnumToStringMapping(context, ref toEnum) || EnumToEnumMapping(context) || EnumToUnderlyingTypeMapping(context, ref toEnum);
- }
-
- private static bool EnumToEnumMapping(ResolutionContext context)
- {
- // Enum to enum mapping
- var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
- var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
- return sourceEnumType != null && destEnumType != null;
- }
-
- private static bool EnumToUnderlyingTypeMapping(ResolutionContext context, ref bool toEnum)
- {
- var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
- var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
-
- // Enum to underlying type
- if (sourceEnumType != null)
- {
- return context.DestinationType.IsAssignableFrom(Enum.GetUnderlyingType(sourceEnumType));
- }
- if (destEnumType != null)
- {
- toEnum = true;
- return context.SourceType.IsAssignableFrom(Enum.GetUnderlyingType(destEnumType));
- }
- return false;
- }
-
- private static bool EnumToStringMapping(ResolutionContext context, ref bool toEnum)
- {
- var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
- var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
-
- // Enum to string
- if (sourceEnumType != null)
- {
- return context.DestinationType.IsAssignableFrom(typeof(string));
- }
- if (destEnumType != null)
- {
- toEnum = true;
- return context.SourceType.IsAssignableFrom(typeof(string));
- }
- return false;
- }
- }
+using System;
+using System.ComponentModel;
+using System.Linq;
+
+namespace AutoMapper.Mappers
+{
+ public class EnumMapper : IObjectMapper
+ {
+ public object Map(ResolutionContext context, IMappingEngineRunner mapper)
+ {
+ bool toEnum = false;
+ Type enumSourceType = TypeHelper.GetEnumerationType(context.SourceType);
+ Type enumDestinationType = TypeHelper.GetEnumerationType(context.DestinationType);
+
+ if (EnumToStringMapping(context, ref toEnum))
+ {
+ if (context.SourceValue == null)
+ {
+ return mapper.CreateObject(context);
+ }
+
+ if (toEnum)
+ {
+ var stringValue = context.SourceValue.ToString();
+ if (string.IsNullOrEmpty(stringValue))
+ {
+ return mapper.CreateObject(context);
+ }
+
+ return Enum.Parse(enumDestinationType, stringValue, true);
+ }
+ return Enum.GetName(enumSourceType, context.SourceValue);
+ }
+ if (EnumToEnumMapping(context))
+ {
+ if (context.SourceValue == null)
+ {
+ return mapper.CreateObject(context);
+ }
+
+ if (!Enum.IsDefined(enumSourceType, context.SourceValue))
+ {
+ return Enum.ToObject(enumDestinationType, context.SourceValue);
+ }
+
+#if !SILVERLIGHT
+ if (!Enum.GetNames(enumDestinationType).Contains(context.SourceValue.ToString()))
+ {
+ Type underlyingSourceType = Enum.GetUnderlyingType(enumSourceType);
+ var underlyingSourceValue = Convert.ChangeType(context.SourceValue, underlyingSourceType);
+
+ return Enum.ToObject(context.DestinationType, underlyingSourceValue);
+ }
+#endif
+
+ return Enum.Parse(enumDestinationType, Enum.GetName(enumSourceType, context.SourceValue), true);
+ }
+ if (EnumToUnderlyingTypeMapping(context, ref toEnum))
+ {
+ if (toEnum)
+ {
+ return Enum.Parse(enumDestinationType, context.SourceValue.ToString(), true);
+ }
+
+ if (EnumToNullableTypeMapping(context))
+ {
+ return ConvertEnumToNullableType(context);
+ }
+
+ return Convert.ChangeType(context.SourceValue, context.DestinationType, null);
+ }
+ return null;
+ }
+
+ public bool IsMatch(ResolutionContext context)
+ {
+ bool toEnum = false;
+ return EnumToStringMapping(context, ref toEnum) || EnumToEnumMapping(context) || EnumToUnderlyingTypeMapping(context, ref toEnum);
+ }
+
+ private static bool EnumToEnumMapping(ResolutionContext context)
+ {
+ // Enum to enum mapping
+ var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
+ var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
+ return sourceEnumType != null && destEnumType != null;
+ }
+
+ private static bool EnumToUnderlyingTypeMapping(ResolutionContext context, ref bool toEnum)
+ {
+ var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
+ var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
+
+ // Enum to underlying type
+ if (sourceEnumType != null)
+ {
+ return context.DestinationType.IsAssignableFrom(Enum.GetUnderlyingType(sourceEnumType));
+ }
+ if (destEnumType != null)
+ {
+ toEnum = true;
+ return context.SourceType.IsAssignableFrom(Enum.GetUnderlyingType(destEnumType));
+ }
+ return false;
+ }
+
+ private static bool EnumToStringMapping(ResolutionContext context, ref bool toEnum)
+ {
+ var sourceEnumType = TypeHelper.GetEnumerationType(context.SourceType);
+ var destEnumType = TypeHelper.GetEnumerationType(context.DestinationType);
+
+ // Enum to string
+ if (sourceEnumType != null)
+ {
+ return context.DestinationType.IsAssignableFrom(typeof(string));
+ }
+ if (destEnumType != null)
+ {
+ toEnum = true;
+ return context.SourceType.IsAssignableFrom(typeof(string));
+ }
+ return false;
+ }
+
+ private static bool EnumToNullableTypeMapping(ResolutionContext context)
+ {
+ if (!context.DestinationType.IsGenericType)
+ {
+ return false;
+ }
+
+ var genericType = context.DestinationType.GetGenericTypeDefinition();
+ return genericType.Equals(typeof(Nullable<>));
+ }
+
+ private static object ConvertEnumToNullableType(ResolutionContext context)
+ {
+ var nullableConverter = new NullableConverter(context.DestinationType);
+ var destType = nullableConverter.UnderlyingType;
+ return Convert.ChangeType(context.SourceValue, destType);
+ }
+
+ }
}
@@ -0,0 +1,36 @@
+using NUnit.Framework;
+
+namespace AutoMapper.UnitTests.Bug
+{
+ [TestFixture]
+ public class CannotConvertEnumToNullable
+ {
+ public enum DummyTypes : int
+ {
+ Foo = 1,
+ Bar = 2
+ }
+
+ public class DummySource
+ {
+ public DummyTypes Dummy { get; set; }
+ }
+
+ public class DummyDestination
+ {
+ public int? Dummy { get; set; }
+ }
+
+ [Test]
+ public void Should_map_enum_to_nullable()
+ {
+ Mapper.CreateMap<DummySource, DummyDestination>();
+ Mapper.AssertConfigurationIsValid();
+ DummySource src = new DummySource() { Dummy = DummyTypes.Bar };
+
+ var destination = Mapper.Map<DummySource, DummyDestination>(src);
+
+ Assert.AreEqual((int)DummyTypes.Bar, destination.Dummy);
+ }
+ }
+}
@@ -107,6 +107,7 @@
<Compile Include="Bug\AllMembersNullSubstitute.cs" />
<Compile Include="Bug\AllowNullDestinationValuesBugs.cs" />
<Compile Include="Bug\AssignableCollectionBug.cs" />
+ <Compile Include="Bug\CannotConvertEnumToNullable.cs" />
<Compile Include="Bug\CollectionMapperMapsISetIncorrectly.cs" />
<Compile Include="Bug\CustomIEnumerableBug.cs" />
<Compile Include="Bug\AddingConfigurationForNonMatchingDestinationMemberBug.cs" />

0 comments on commit 19f0cb7

Please sign in to comment.