Skip to content

Commit f93c059

Browse files
authored
Merge pull request #2232 from AutoMapper/ConsolidateNullable
Consolidate destination nullable mappings
2 parents 2ea4d2c + 3851ebe commit f93c059

11 files changed

+36
-30
lines changed

src/AutoMapper/ConfigurationValidator.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,6 @@ private void DryRunTypeMap(ICollection<TypeMap> typeMapsChecked, TypePair types,
7777
else
7878
{
7979
var mapperToUse = _config.FindMapper(types);
80-
if (mapperToUse == null && types.SourceType.IsNullableType())
81-
{
82-
var nullableTypes = new TypePair(Nullable.GetUnderlyingType(types.SourceType),
83-
types.DestinationType);
84-
mapperToUse = _config.FindMapper(nullableTypes);
85-
}
8680
if (mapperToUse == null)
8781
{
8882
throw new AutoMapperConfigurationException(types) { PropertyMap = propertyMap };

src/AutoMapper/Execution/TypeMapPlanBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ private Expression BuildValueResolverFunc(PropertyMap propertyMap, Expression de
472472
var returnType = destinationNullable && destinationPropertyType.GetTypeOfNullable() ==
473473
nullCheckedExpression.Type
474474
? destinationPropertyType
475-
: nullCheckedExpression.Type;
475+
: nullCheckedExpression.Type;
476476
valueResolverFunc =
477477
TryCatch(
478478
ToType(nullCheckedExpression, returnType),

src/AutoMapper/Mappers/ConvertMapper.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private static Dictionary<TypePair, LazyExpression> GetConverters()
2323
};
2424
return
2525
(from sourceType in primitiveTypes
26-
from destinationType in primitiveTypes.Concat(from type in primitiveTypes.Where(t => t.IsValueType()) select typeof(Nullable<>).MakeGenericType(type))
26+
from destinationType in primitiveTypes
2727
select new
2828
{
2929
Key = new TypePair(sourceType, destinationType),
@@ -34,8 +34,7 @@ from destinationType in primitiveTypes.Concat(from type in primitiveTypes.Where(
3434

3535
static LambdaExpression ConvertExpression(Type sourceType, Type destinationType)
3636
{
37-
var underlyingDestinationType = Nullable.GetUnderlyingType(destinationType) ?? destinationType;
38-
var convertMethod = typeof(Convert).GetDeclaredMethod("To" + underlyingDestinationType.Name, new[] { sourceType });
37+
var convertMethod = typeof(Convert).GetDeclaredMethod("To" + destinationType.Name, new[] { sourceType });
3938
var sourceParameter = Parameter(sourceType, "source");
4039
return Lambda(Call(convertMethod, sourceParameter), sourceParameter);
4140
}

src/AutoMapper/Mappers/EnumToUnderlyingTypeMapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public Expression MapExpression(IConfigurationProvider configurationProvider, Pr
2626
Expression contextExpression) =>
2727
ToType(
2828
Call(ChangeTypeMethod, ToObject(sourceExpression),
29-
Constant(Nullable.GetUnderlyingType(destExpression.Type) ?? destExpression.Type)),
29+
Constant(destExpression.Type)),
3030
destExpression.Type
3131
);
3232
}

src/AutoMapper/Mappers/FlagsEnumMapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public Expression MapExpression(IConfigurationProvider configurationProvider, Pr
3030
Expression contextExpression) =>
3131
ToType(
3232
Call(EnumParseMethod,
33-
Constant(Nullable.GetUnderlyingType(destExpression.Type) ?? destExpression.Type),
33+
Constant(destExpression.Type),
3434
Call(sourceExpression, sourceExpression.Type.GetDeclaredMethod("ToString")),
3535
Constant(true)
3636
),

src/AutoMapper/Mappers/ImplicitConversionOperatorMapper.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ public bool IsMatch(TypePair context)
1717
private static MethodInfo GetImplicitConversionOperator(TypePair context)
1818
{
1919
var destinationType = context.DestinationType;
20-
if(destinationType.IsNullableType())
21-
{
22-
destinationType = destinationType.GetTypeOfNullable();
23-
}
2420
var sourceTypeMethod = context.SourceType
2521
.GetDeclaredMethods()
2622
.FirstOrDefault(mi => mi.IsPublic && mi.IsStatic && mi.Name == "op_Implicit" && mi.ReturnType == destinationType);

src/AutoMapper/Mappers/Internal/ElementTypeHelper.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ public static Type[] GetElementTypes(Type enumerableType, IEnumerable enumerable
4949

5050
public static Type GetEnumerationType(Type enumType)
5151
{
52-
if (enumType.IsNullableType())
53-
{
54-
enumType = enumType.GetTypeInfo().GenericTypeArguments[0];
55-
}
56-
5752
return !enumType.IsEnum() ? null : enumType;
5853
}
5954

src/AutoMapper/Mappers/MapperRegistry.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ internal static class MapperRegistry
77
public static IList<IObjectMapper> Mappers() => new List<IObjectMapper>
88
{
99
new NullableSourceMapper(),
10+
new NullableDestinationMapper(),
1011
new ExpressionMapper(),
1112
new FlagsEnumMapper(),
1213
new StringToEnumMapper(),
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Linq.Expressions;
3+
using AutoMapper.Configuration;
4+
using AutoMapper.Execution;
5+
6+
namespace AutoMapper.Mappers
7+
{
8+
public class NullableDestinationMapper : IObjectMapperInfo
9+
{
10+
public bool IsMatch(TypePair context) => context.DestinationType.IsNullableType();
11+
12+
public Expression MapExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap,
13+
PropertyMap propertyMap, Expression sourceExpression, Expression destExpression,
14+
Expression contextExpression) =>
15+
ExpressionBuilder.MapExpression(configurationProvider, profileMap,
16+
new TypePair(sourceExpression.Type, Nullable.GetUnderlyingType(destExpression.Type)),
17+
sourceExpression,
18+
contextExpression,
19+
propertyMap,
20+
Expression.Property(destExpression, destExpression.Type.GetDeclaredProperty("Value"))
21+
);
22+
23+
public TypePair GetAssociatedTypes(TypePair initialTypes)
24+
{
25+
return new TypePair(initialTypes.SourceType, Nullable.GetUnderlyingType(initialTypes.DestinationType));
26+
}
27+
}
28+
}

src/AutoMapper/Mappers/TypeConverterMapper.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ private static TDestination Map<TSource, TDestination>(TSource source)
1919
return (TDestination)typeConverter.ConvertTo(source, typeof(TDestination));
2020
}
2121

22-
if (typeof(TDestination).IsNullableType() &&
23-
typeConverter.CanConvertTo(Nullable.GetUnderlyingType(typeof(TDestination))))
24-
{
25-
return (TDestination)typeConverter.ConvertTo(source, Nullable.GetUnderlyingType(typeof(TDestination)));
26-
}
27-
2822
typeConverter = GetTypeConverter(typeof(TDestination));
2923
if (typeConverter.CanConvertFrom(typeof(TSource)))
3024
{
@@ -41,8 +35,7 @@ public bool IsMatch(TypePair context)
4135
var sourceTypeConverter = GetTypeConverter(context.SourceType);
4236
var destTypeConverter = GetTypeConverter(context.DestinationType);
4337

44-
return sourceTypeConverter.CanConvertTo(context.DestinationType) || context.DestinationType.IsNullableType() &&
45-
sourceTypeConverter.CanConvertTo(Nullable.GetUnderlyingType(context.DestinationType)) || destTypeConverter.CanConvertFrom(context.SourceType);
38+
return sourceTypeConverter.CanConvertTo(context.DestinationType) || destTypeConverter.CanConvertFrom(context.SourceType);
4639
}
4740

4841
public Expression MapExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap,

0 commit comments

Comments
 (0)