如何将参数传递给基本映射配置文件的构造函数?

问题描述 投票:0回答:1

我目前正在将几个映射配置文件从Automapper 4.2.1迁移到最新版本9.0.0。旧的映射配置文件是按层次结构构建的,其中抽象基类需要类型为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 
    }   
}

现在,我想移至新的IncludeIncludeBase<>方法并撤消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>();
    }
}

那么如何将参数传递给base类的构造函数?还有其他可能性吗?

c# automapper automapper-4
1个回答
0
投票

再次感谢Lucian。我通过为AddProfile提供配置文件instance来解决了该问题(而不是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具有无代码重复的好处。但是另一方面,更复杂的配置文件和测试设置尤其是在这种情况下。

© www.soinside.com 2019 - 2024. All rights reserved.