0

我目前正在将几个映射配置文件从 Automapper 4.2.1 迁移到最新版本 9.0.0。旧的映射配置文件是分层构建的,其中抽象基类需要 type 的参数IDatetime。此注入仅用于测试。

public abstract MappingProfileBase : Profile 
{
    protected MappingProfileBase(IDatetime datetime)
    {
        this.CreateMap<Foo, FooDto>()
            .ForMember(dest => dest.SomeTimeStamp, opt => opt.MapFrom(src => datetime));
            // Further mappings 
    }
}

public MappingProfileA : MappingProfileBase
{
    public MappingProfileA(IDatetime datetime) : base(datetime)
    {
        this.CreateMap<FooDerived, FooDerivedDto>()        
            // Further and more specific mappings 
    }   
}

现在我想转到新的IncludeandIncludeBase<>方法并撤消对 and 的继承,MappingProfileAMappingProfileBase根本不知道如何处理注入的接口。没有一个新方法接受任何参数。

我认为它应该是这样的:

public class MappingProfileBase : Profile
{
    public MappingProfileBase(IDatetime datetime)
    {
        this.CreateMap<Foo, FooDto>()
            .ForMember(dest => dest.SomeTimeStamp, opt => opt.MapFrom(src => datetime));
            // Further mappings
    }
}

public class MappingProfileA : Profile
{
    public MappingProfileA()
    {
        this.CreateMap<FooDerived, FooDerivedDto>();
            .IncludeBase<Foo, FooDto>();
    }
}

那么如何将参数传递给类的构造函数呢?还存在哪些其他可能性?

4

1 回答 1

0

(再次)感谢卢锡安。我通过使用 Autofac 向(而不是 )提供配置文件实例来 解决它因此,我必须事先将具体类型注册到容器中。AddProfileType

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的好处是没有代码重复。但另一方面,更复杂的配置文件和测试设置尤其是在这种情况下。

于 2019-10-22T13:50:27.777 回答