Спасибо (снова) Люциану. Я решил это путем предоставления профиля экземпляр до AddProfile
(вместо Type
) с использованием Autofac. Для этого мне пришлось заранее зарегистрировать конкретный тип контейнера.
private static MapperConfiguration GetMappingConfiguration()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<DateTime>().As<IDateTime>();
var assembly = Assembly.GetExecutingAssembly();
var loadedProfiles = assembly.ExportedTypes
.Where(type => type.IsSubclassOf(typeof(Profile)))
.ToArray();
containerBuilder.RegisterTypes(loadedProfiles);
var container = containerBuilder.Build();
var config = new MapperConfiguration(cfg =>
{
cfg.ConstructServicesUsing(container.Resolve);
foreach (var profile in loadedProfiles)
{
var resolvedProfile = container.Resolve(profile) as Profile;
cfg.AddProfile(resolvedProfile);
}
});
return config;
}
Вот два примера профилей:
public class BaseMappingProfile : Profile
{
public BaseMappingProfile(IDateTime datetime)
{
this.CreateMap<Foo, FooDto>()
.ForMember(d => d.Timestamp, o => o.MapFrom(s => datetime))
.ForMember(d => d.PropertyA, o => o.MapFrom(s => s.Property1));
}
}
public class FooMappingProfile : Profile
{
public FooMappingProfile()
{
this.CreateMap<FooDerived, FooDerivedDto>()
.IncludeBase<Foo, FooDto>()
.ForMember(d => d.PropertyB, o => o.MapFrom(s => s.Property2));
}
}
А затем в рамках модульного теста:
[Fact]
public void Should_Map_From_Foo_To_FooDto()
{
var config = GetMappingConfiguration();
var mapper = config.CreateMapper();
var foo = new Foo {Property1 = "I am property 1"};
var fooDto = mapper.Map<FooDto>(foo);
// Asserts...
}
Конечно, статический метод GetMappingConfiguration
требуетдальнейшая модификация. Но в принципе это работает.
Использование IncludeBase
позволяет избежать дублирования кода. Но с другой стороны, более сложные профили и настройка теста особенно в этом случае.