使用内联映射的Automapper自定义解析器会导致测试失败



得到一个映射器配置,其中包括:

this.CreateMap<MyProp1, MyDesintationProp>();
this.CreateMap<MyProp2, MyDesintationProp>();

然后,在更复杂对象的映射器中,这两个都在内联ResolveUsing中使用,以合并到MyDestinationProp:的列表中

.ForMember(dest => dest.MyDesintationPropList, opt => opt.ResolveUsing(tc =>
{
var results = new List<MyDesintationProp>();

if (tc.MyProp1 != null)
{
results.Add(Mapper.Map<MyDestinationProp>(tc.MyProp1));
}
if (tc.MyProp2 != null)
{
results.Add(Mapper.Map<MyDestinationProp>(tc.MyProp2));
}
return results;
}))

这在生产中运行良好,但导致对该映射的测试失败,抱怨

属性:MyDestinationProp----System.InvalidOperationException:映射器未初始化。使用适当的配置调用Initialize。如果您试图通过容器或其他方式使用映射器实例,请确保没有任何对静态mapper.Map方法的调用,如果您使用ProjectTo或UseAsDataSource扩展方法,请确保传入适当的IConfigurationProvider实例。

我想这是有道理的,因为映射器中的映射器尚未初始化。但是,解决这个问题的最佳方法是什么?

这是一个非常琐碎的例子,它实际上不需要使用上下文,因为它也可以使用简单的映射。

public class Source
{
public string Name { get; set; }
public SourceChild Child { get; set; }
public override string ToString() => $"{typeof(Source)} -> {Name}";
}
public class Destination
{
public string Name { get; set; }
public DestinationChild Child { get; set; }
public override string ToString() => $"{typeof(Destination)} -> {Name}";
}
public class SourceChild
{
public string Name { get; set; }
public override string ToString() => $"{typeof(SourceChild)} -> {Name}";
}
public class DestinationChild
{
public string Name { get; set; }
public override string ToString() => $"{typeof(DestinationChild)} -> {Name}";
}
public class MappingContextProfile : Profile
{
public MappingContextProfile()
{
CreateMap<Source, Destination>()
.ForMember(source => source.Child, conf => conf.MapFrom((source, destination, destinationChild, context) =>
{
// Not really needed in this case, cause it does just some simple mapping.
// But if you would need to add some informations from outside
// (e.g. some interface mapping, etc)
// this would be the place without losing the magic of AutoMapper.
return context.Mapper.Map<DestinationChild>(source.Child);
}));
CreateMap<SourceChild, DestinationChild>();
}
}
public class MappingSimpleProfile : Profile
{
public MappingSimpleProfile()
{
CreateMap<Source, Destination>();
CreateMap<SourceChild, DestinationChild>();
}
}

public static class Program
{
public static async Task<int> Main(string[] args)
{
var config = new MapperConfiguration(cfg => cfg.AddProfile<MappingContextProfile>());
var mapper = config.CreateMapper();
var sources = Enumerable.Range(1, 10)
.Select(i => new Source { Name = $"{i}", Child = new SourceChild { Name = $"{i * 100}" } })
.ToList();
var destinations = mapper.Map<List<Destination>>(sources);
foreach (var item in destinations)
{
Console.WriteLine($"{item} -> {item.Child}");
}
return 0;
}
}

最新更新