修改现有的AutoMapper类型映射(用于单元测试)
本文关键字:用于 单元测试 映射 类型 AutoMapper 修改 | 更新日期: 2023-09-27 18:08:59
我使用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());
我想把后面的代码移到单元测试方法中,所以它看起来像这样:
[TestMethod]
public void TestMappingConfiguration()
{
Mapper.AddProfile<MyProfile>();
Mapper.FindTypeMapFor<SourceType, DestinationType>()
.ForMember(dest => dest.IgnoredMember, opt => opt.Ignore());
Mapper.AssertConfigurationIsValid(MyProfile.Name);
}
在Mapper类中已经有FindTypeMapFor方法,但是我找不到一个好方法来将被忽略的属性添加到映射中。这可能吗?
我已经做到了我想做的。下面是一个带有扩展方法的主类,它可以向现有的映射添加一个被忽略的属性:
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)));
}
}
类TypeMap只不过是原始TypeMap的包装器。泛型版本的要点是允许流畅的语法(见下文)。
从AutoMapper源代码中借用的ReflectionHelper类。它依赖于来自AutoMapper的其他五个类。内部命名空间,所以它们也是借来的。
最后,所有这些允许我编写以下代码:
TypeMap<SourceType, DestinationType>.Get()
.AddIgnoredMember(dest => dest.IgnoredMember)
.AddIgnoredMember(dest => dest.AnotherIgnoredMember);
是否可以先忽略所有成员,然后为需要的属性提供特定的映射?我以前创建了一个扩展来帮助解决这个问题:
public static IMappingExpression<TSource, TDest>
IgnoreAllUnmapped<TSource, TDest>(
this IMappingExpression<TSource, TDest> expression)
{
expression.ForAllMembers(opt => opt.Ignore());
return expression;
}
然后你可以这样写
CreateMap<SourceType, DestinationType>()
.IgnoreAllUnmapped()
.ForMember(d => d.DestMember, opt => opt.MapFrom(s => s.SourceMember))