Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,19 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
: GetInstanceExpression(this.Visit(node.Object));

MethodCallExpression GetInstanceExpression(Expression instance)
=> node.Method.IsGenericMethod
? Expression.Call(instance, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
: Expression.Call(instance, instance.Type.GetMethod(node.Method.Name, listOfArgumentsForNewMethod.Select(a => a.Type).ToArray()), listOfArgumentsForNewMethod.ToArray());
{
return node.Method.IsGenericMethod
? Expression.Call(instance, node.Method.Name, typeArgsForNewMethod.ToArray(), listOfArgumentsForNewMethod.ToArray())
: Expression.Call(instance, GetMethodInfoForNonGeneric(), listOfArgumentsForNewMethod.ToArray());

MethodInfo GetMethodInfoForNonGeneric()
{
MethodInfo methodInfo = instance.Type.GetMethod(node.Method.Name, listOfArgumentsForNewMethod.Select(a => a.Type).ToArray());
if (methodInfo.DeclaringType != instance.Type)
methodInfo = methodInfo.DeclaringType.GetMethod(node.Method.Name, listOfArgumentsForNewMethod.Select(a => a.Type).ToArray());
return methodInfo;
}
}

MethodCallExpression GetStaticExpression()
=> node.Method.IsGenericMethod
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Xunit;

namespace AutoMapper.Extensions.ExpressionMapping.UnitTests
{
public class ShouldUseDeclaringTypeForInstanceMethodCalls
{
[Fact]
public void MethodInfoShouldRetainDeclaringTypeInMappedExpression()
{
//Arrange
var config = new MapperConfiguration
(
cfg =>
{
cfg.CreateMap<EntityModel, Entity>();
cfg.CreateMap<Entity, EntityModel>();
}
);
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
Expression<Func<Entity, bool>> filter = e => e.SimpleEnum.HasFlag(SimpleEnum.Value3);
EntityModel entityModel1 = new() { SimpleEnum = SimpleEnumModel.Value3 };
EntityModel entityModel2 = new() { SimpleEnum = SimpleEnumModel.Value2 };

//act
Expression<Func<EntityModel, bool>> mappedFilter = mapper.MapExpression<Expression<Func<EntityModel, bool>>>(filter);

//assert
Assert.Equal(typeof(Enum), HasFlagVisitor.GetasFlagReflectedType(mappedFilter));
Assert.Single(new List<EntityModel> { entityModel1 }.AsQueryable().Where(mappedFilter));
Assert.Empty(new List<EntityModel> { entityModel2 }.AsQueryable().Where(mappedFilter));
}

public enum SimpleEnum
{
Value1,
Value2,
Value3
}

public record Entity
{
public int Id { get; init; }
public SimpleEnum SimpleEnum { get; init; }
}

public enum SimpleEnumModel
{
Value1,
Value2,
Value3
}

public record EntityModel
{
public int Id { get; init; }
public SimpleEnumModel SimpleEnum { get; init; }
}

public class HasFlagVisitor : ExpressionVisitor
{
public static Type GetasFlagReflectedType(Expression expression)
{
HasFlagVisitor hasFlagVisitor = new();
hasFlagVisitor.Visit(expression);
return hasFlagVisitor.HasFlagReflectedType;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == "HasFlag")
HasFlagReflectedType = node.Method.ReflectedType;

return base.VisitMethodCall(node);
}

public Type HasFlagReflectedType { get; private set; }
}
}
}