修改现有的AutoMapper类型映射(用于单元测试)

Ale*_*Che 3 unit-testing automapper

我使用AssertConfigurationIsValid方法对我的映射配置文件进行单元测试.为了使它接受我的映射,我需要显式地忽略未映射的目标属性.这会污染我的映射代码并降低其可读性.由于仅在AssertConfigurationIsValid传递的单元测试中需要这样做,所以我想将"忽略"代码移动到相同的单元测试中.

考虑来自某个映射配置文件类的以下映射代码:

CreateMap<SourceType, DestinationType>()
   // here goes some actual mapping code:
   .ForMember(dest => dest.DestMember, opt => opt.MapFrom(src => src.SourceMember))
   // and then go the explicitly ignored unmapped dest members,
   // just for AssertConfigurationIsValid to pass:
   .ForMember(dest => dest.IgnoredMember, opt => opt.Ignore());
Run Code Online (Sandbox Code Playgroud)

我想将后一个代码移动到单元测试方法,因此它将如下所示:

[TestMethod]
public void TestMappingConfiguration()
{
  Mapper.AddProfile<MyProfile>();
  Mapper.FindTypeMapFor<SourceType, DestinationType>()
    .ForMember(dest => dest.IgnoredMember, opt => opt.Ignore());
  Mapper.AssertConfigurationIsValid(MyProfile.Name);
}
Run Code Online (Sandbox Code Playgroud)

Mapper类中已经存在FindTypeMapFor方法,但我找不到向映射添加忽略属性的好方法.这可能吗?

Ale*_*Che 5

我设法做了我想做的事.这是一个主类,它有一个扩展方法,用于向现有地图添加一个被忽略的属性:

  static class TypeMapExtensions
  {
    public static TypeMap<TSource, TDestination> AddIgnoredMember<TSource, TDestination>(
      this TypeMap<TSource, TDestination> typeMap, 
      Expression<Func<TDestination, object>> accessorExpression)
    {
      MemberInfo memberInfo = ReflectionHelper.FindProperty(accessorExpression);
      IMemberAccessor memberAccessor = memberInfo.ToMemberAccessor();
      var propertyMap = new PropertyMap(memberAccessor);
      propertyMap.Ignore();
      AddPropertyMap(typeMap.Map, propertyMap);
      return typeMap;
    }

    private static void AddPropertyMap(TypeMap typeMap, PropertyMap propertyMap)
    {
      typeMap.AddPropertyMap(propertyMap);
      if (typeMap.HasDerivedTypesToInclude())
      {
        IEnumerable<TypeMap> derivedMaps = GetDerivedMaps(typeMap);
        foreach (var derivedMap in derivedMaps)
          derivedMap.AddInheritedPropertyMap(propertyMap);
      }
    }

    private static IEnumerable<TypeMap> GetDerivedMaps(TypeMap typeMap)
    {
      return Mapper.GetAllTypeMaps().Where(
        map =>
          (map.Profile == typeMap.Profile) &&
          (typeMap.TypeHasBeenIncluded(map.SourceType, map.DestinationType)));
    }
  }
Run Code Online (Sandbox Code Playgroud)

TypeMap类只不过是对原始TypeMap的包装器.通用版本的要点是允许流畅的语法(见下文).

ReflectionHelper类借用了AutoMapper源代码.它取决于AutoMapper.Internal命名空间中的其他五个类,因此它们也被借用.

最后,所有这些允许我编写以下代码:

TypeMap<SourceType, DestinationType>.Get()
  .AddIgnoredMember(dest => dest.IgnoredMember)
  .AddIgnoredMember(dest => dest.AnotherIgnoredMember);
Run Code Online (Sandbox Code Playgroud)