繁体   English   中英

升级到 9 后无法访问自动映射器上下文项

[英]Can't access automapper context items after upgrade to 9

我有一个这样的映射器:

CreateMap<Source, ICollection<Dest>>()
    .ConvertUsing((src, dst, context) => 
    {
        return context.Mapper.Map<ICollection<Dest>>
            (new SourceItem[] { src.Item1, src.Item2 ... }.Where(item => SomeFilter(item)),
            opts => opts.Items["SomethingFromSource"] = src.Something);
    });

CreateMap<SourceItem, Dest>()
    .ForMember(d => d.Something, opts => opts.MapFrom((src, dst, dstItem, context)
        => (string)context.Items["SomethingFromSource"]));

这给了我一个例外,说You must use a Map overload that takes Action<IMappingOperationOptions> 好吧,我确实使用了执行此操作的Map重载。 我还能怎么做?

这是因为这个变化:
https://github.com/AutoMapper/AutoMapper/pull/3150

您可以通过访问 ResolutionContext 的 Options 属性来获取项目。

context.Items["SomethingFromSource"]更改为context.Options.Items["SomethingFromSource"]

当没有 Items 时, ResolutionContextDefaultContext相同。 因此ResolutionContext.Items属性将引发异常。
但是,如果有, ResolutionContext.Items将与DefaultContext不同。 因此ResolutionContext.Items将返回列表。

虽然ResolutionContext.Options.Items将始终返回列表,但它不会抛出任何异常,无论它是否为空。 我相信这是错误消息的意思,因为ResolutionContext.Options是一个IMappingOperationOptions

此扩展可以帮助迁移到 AutoMapper 12

public static class AutoMapperExtensions
{
    public static TDestination MapOptions<TDestination>(this IMapper mapper, object source, Action<IMappingOperationOptions<object, TDestination>> OptionalOptions = null)
    {
        return mapper.Map(source, OptionalOptions ?? (_ => {}) );
    }
}

在注入了 IMapper 的 Class 中

public class Command
{
    protected readonly IMapper AutoMapper;

    public Command(IMapper mapper)
    {
        AutoMapper = mapper;
    }

    private SomethingToDo()
    {
        var list = new List<string>();
        // change for 12
        var result = AutoMapper.MapOptions<IList<Item>>(list);
        // prior to 12
        //var result = AutoMapper.Map<IList<Item>>(list);
    }
}

使用内部映射器时的几点考虑(即context.Mapper

首先,尽量不要使用context.Mapper.Map<TDestination>(...) ,而是使用context.Mapper.Map<TSource, TDestination>(...) ,它的表现要好得多。

其次,在内部映射器中使用上下文会破坏封装。 如果您需要在内部对象中设置值,请考虑以下两种解决方案:

如果您想在内部 map 之后设置值

context.Mapper.Map<Source, Dest> (source, opts => opts.AfterMap((s, d) => 
    d.Something = source.Something))

如果您想在内部 map 之前设置值

context.Mapper.Map<Source, Dest> (source, new Dest()
    {
        Something = source.Something
    })

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM