Skip to content

Commit a28b89b

Browse files
authored
Merge pull request #13 from BlaiseD/master
Allow mapping of generic methods in expressions irrespective of the parameter.
2 parents d70bafc + 3c0be93 commit a28b89b

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<Authors>Jimmy Bogard</Authors>
44
<LangVersion>latest</LangVersion>
5-
<VersionPrefix>1.0.3</VersionPrefix>
5+
<VersionPrefix>1.0.4</VersionPrefix>
66
<WarningsAsErrors>true</WarningsAsErrors>
77
<NoWarn>$(NoWarn);1701;1702;1591</NoWarn>
88
</PropertyGroup>

src/AutoMapper.Extensions.ExpressionMapping/MapperExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ TDestDelegate GetLambda(Dictionary<Type, Type> typeMappings, XpressionMapperVisi
6969
return (TDestDelegate)Lambda
7070
(
7171
typeDestFunc,
72-
ExpressionFactory.ToType(remappedBody, typeDestFunc.GetGenericArguments().Last()),
72+
typeDestFunc.IsFuncType() ? ExpressionFactory.ToType(remappedBody, typeDestFunc.GetGenericArguments().Last()) : remappedBody,
7373
expression.GetDestinationParameterExpressions(visitor.InfoDictionary, typeMappings)
7474
);
7575
}
7676
}
7777

78+
private static bool IsFuncType(this Type type)
79+
=> type.FullName.StartsWith("System.Func");
7880

7981
/// <summary>
8082
/// Maps an expression given a dictionary of types where the source type is the key and the destination type is the value.

src/AutoMapper.Extensions.ExpressionMapping/XpressionMapperVisitor.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,11 @@ protected override Expression VisitConstant(ConstantExpression node)
146146
protected override Expression VisitMethodCall(MethodCallExpression node)
147147
{
148148
var parameterExpression = node.GetParameterExpression();
149-
if (parameterExpression == null)
150-
return base.VisitMethodCall(node);
151-
152-
InfoDictionary.Add(parameterExpression, TypeMappings);
149+
if (parameterExpression != null)
150+
InfoDictionary.Add(parameterExpression, TypeMappings);
153151

154152
var listOfArgumentsForNewMethod = node.Arguments.Aggregate(new List<Expression>(), (lst, next) =>
155153
{
156-
//var mappedNext = ArgumentMapper.Create(this, next).MappedArgumentExpression;
157-
//Using VisitUnary and VisitLambda instead of ArgumentMappers
158154
var mappedNext = this.Visit(next);
159155
TypeMappings.AddTypeMapping(ConfigurationProvider, next.Type, mappedNext.Type);
160156

@@ -169,11 +165,6 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
169165

170166
ConvertTypesIfNecessary(node.Method.GetParameters(), listOfArgumentsForNewMethod, node.Method);
171167

172-
/*Using VisitUnary and VisitLambda instead of ArgumentMappers
173-
* return node.Method.IsStatic
174-
? GetStaticExpression()
175-
: GetInstanceExpression(ArgumentMapper.Create(this, node.Object).MappedArgumentExpression);*/
176-
177168
return node.Method.IsStatic
178169
? GetStaticExpression()
179170
: GetInstanceExpression(this.Visit(node.Object));

tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/XpressionMapperTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,40 @@ public void Can_correctly_type_maps_for_child_properties()
601601
//Assert
602602
Assert.NotNull(dest);
603603
}
604+
605+
[Fact]
606+
public void Can_map_expressions_with_no_parameters()
607+
{
608+
//Arrange
609+
Expression<Func<OptionS>> exp = () => Activator.CreateInstance<OptionS>();
610+
611+
//Act
612+
Expression<Func<OptionT>> expmapped = mapper.Map<Expression<Func<OptionS>>, Expression<Func<OptionT>>>(exp);
613+
614+
//Assert
615+
Assert.True(expmapped.Type == typeof(Func<OptionT>));
616+
}
617+
618+
619+
[Fact]
620+
public void Can_map_expressions_with_action_independent_of_expression_param()
621+
{
622+
//Arrange
623+
Expression<Action<OptionS>> exp = (s) => CallSomeAction<OptionS>(Activator.CreateInstance<OptionS>());
624+
625+
//Act
626+
Expression<Action<OptionT>> expmapped = mapper.MapExpression<Expression<Action<OptionS>>, Expression<Action<OptionT>>>(exp);
627+
628+
//Assert
629+
expmapped.Compile()(Activator.CreateInstance<OptionT>());
630+
Assert.True(this.val.GetType() == typeof(OptionT));
631+
}
632+
633+
object val;
634+
void CallSomeAction<T>(T val)
635+
{
636+
this.val = val;
637+
}
604638
#endregion Tests
605639

606640
private static void SetupAutoMapper()
@@ -698,6 +732,16 @@ private static void SetupQueryableCollection()
698732
private static IQueryable<User> Users { get; set; }
699733
}
700734

735+
public class OptionS
736+
{
737+
public static OptionS GetNew() => new OptionS();
738+
}
739+
740+
public class OptionT
741+
{
742+
public static OptionT GetNew() => new OptionT();
743+
}
744+
701745
public class Account
702746
{
703747
public Account()
@@ -1066,6 +1110,8 @@ public OrganizationProfile()
10661110
.ForMember(x => x.Items, opt => opt.MapFrom(x => x.OrderData.Items));
10671111
CreateMap<ItemEntity, ItemModel>();
10681112

1113+
CreateMap<OptionT, OptionS>();
1114+
10691115
CreateMissingTypeMaps = true;
10701116
}
10711117
}

0 commit comments

Comments
 (0)