0

使用以下示例(LinqPad):

void Main()
{

    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Source, DestinationNested>()
            .ConstructUsing((source, context) => new DestinationNested(source.InnerValue));

        cfg.CreateMap<Source, DestinationOuter>()
            .ForMember(x => x.OuterValue, y => y.MapFrom(z => z.OuterValue))
            .ConstructUsing((source, context) =>
            {
                return new DestinationOuter(source.OuterValue, context.Mapper.Map<DestinationNested>(source));
            });

    });

    var src = new Source { OuterValue = 999, InnerValue = 111 };

    var mapper = config.CreateMapper();
    var mapped = mapper.Map<DestinationOuter>(src);

    mapped.Dump();

    mapper.ConfigurationProvider.AssertConfigurationIsValid();
}

public class Source
{
    public int OuterValue { get; set; }
    public int InnerValue { get; set; }
}

public class DestinationOuter
{
    public int OuterValue { get; private set; }
    public DestinationNested destinationNested { get; private set; }

    public DestinationOuter(int outerValue, DestinationNested destinationNested)
    {
        this.OuterValue = outerValue;
        this.destinationNested = destinationNested;
    }
}

public class DestinationNested
{
    public int NestedValue { get; private set; }

    public DestinationNested(int nestedValue)
    {
        this.NestedValue = nestedValue;
    }
}

AssertConfigurationIsValid() 当前在我使用 ContructUsing 时引发有关属性的异常。

实际上它确实映射正确,但我希望 AssertConfigurationIsValid 作为我的测试套件的一部分来查找回归(无需对映射器进行手动测试)。

我想保证我的所有属性都通过构造函数从源映射到目标。我希望使用一个构造器,因为它是我的域层,并且构造器强制执行强制性项目。

我不希望通过 IgnoreAllPropertiesWithAnInaccessibleSetter() 功能忽略所有私有设置器,因为我可能会忽略一些我实际上没有设置的东西。

理想情况下,我也不想对出现在构造函数中的每个属性进行手动 Ignore() 操作,因为这会导致代码漂移。

我在 Automapper 中尝试了各种组合,但到目前为止还没有运气。

我想这是一个静态分析挑战;我想知道我的承包商涵盖了 Destination 中的所有属性。而且我想知道构造函数是从源头传递的。

我意识到 Automapper 在这一点上并不是很自动化,有没有一种很好的方法可以依靠 automapper 进行此测试,或者这是否是一个静态分析问题?

4

2 回答 2

1

这是我的看法。

static void Main(string[] args)
{
    try{
    var mapperCfg = new AutoMapper.MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Source, DestinationOuter>().ForCtorParam("destinationNested", o => o.MapFrom(s => new DestinationNested(s.InnerValue)));
    });
    mapperCfg.AssertConfigurationIsValid();
    var mapper = mapperCfg.CreateMapper();

    var src = new Source { OuterValue = 999, InnerValue = 111 };
    mapper.Map<DestinationOuter>(src).Dump();
    }catch(Exception ex){
        ex.ToString().Dump();
    }
}
public class Source
{
    public int OuterValue { get; set; }
    public int InnerValue { get; set; }
}
public class DestinationOuter
{
    public int OuterValue { get; }
    public DestinationNested DestinationNested { get; }

    public DestinationOuter(int outerValue, DestinationNested destinationNested)
    {
        this.OuterValue = outerValue;
        this.DestinationNested = destinationNested;
    }
}
public class DestinationNested
{
    public int NestedValue { get; private set; }

    public DestinationNested(int nestedValue)
    {
        this.NestedValue = nestedValue;
    }
}
于 2019-10-26T05:28:28.117 回答
0

在阅读了大量文档、使用调试器逐步完成集成测试和几天的优秀实验之后,这是我拥有的最好的:

var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Source, DestinationNested>()
            .ForCtorParam("nestedValue", x => x.MapFrom(y => y.InnerValue))
            .ForMember(x => x.NestedValue, x => x.MapFrom(y => y.InnerValue));

        cfg.CreateMap<Source, DestinationOuter>()
            .ForPath(x => x.destinationNested.NestedValue, x => x.MapFrom(y => y.InnerValue))
            .ForCtorParam("destinationNested", x => x.MapFrom(y => y));
    });

我对此很满意;它摆脱了在我更广泛的代码库中构造嵌套对象的 ContructUsing() 气味。如果我的目标对象未填充,它会警告我。理想情况下,构造函数参数字符串将是类型安全的,但我理解它为什么不能(也许这是另一天有趣的 Roslyn 代码分析器项目的东西:-))

秘密调味料(新闻界的热门)是x => x.MapFrom(y => y)再加上.ForPath(x => x.destinationNested.NestedValue, x => x.MapFrom(y => y.InnerValue))它似乎给 AutoMapper 足够的提示,即 destinationNested 与 InnerValue 相关,并且 contructor 参数被重命名为“destinationNested”。神奇之处在于它没有使用上下文来构造嵌套对象,看起来无辜的x.MapFrom(y => y)似乎让它使用属性映射来代替*。

*这是我的外行解释,我还没有遵循足够的AutoMapper源代码来真正理解属性映射和构造函数映射之间的关系。阅读一些 GitHub 票证,我认为它们是独立的概念。

我也没有x.MapFrom(y => y)在文档中看到提到过,所以我有兴趣了解更多关于它的信息。

于 2019-10-25T20:14:59.160 回答