简体   繁体   中英

Resolver lifetime when mapping with a custom value resolver

I am using AutoMapper v9.0.0, I have source and destination objects which both contain a one to many parent/child relationship.

When the map is invoked, a sequence of ~100k SrcParent objects with < 100 SrcChild objects are processed. Each parent map is invoked individually so an existing instance of a DstParent object can be seeded with a DstParent.ConfigurationId value, the MyValueResolver value resolver can only perform the SrcChild to DstChild conversion with this data.

The mapper is added to the asp.net core di container with the lifetime overridden using services.AddAutoMapper(assemblies, ServiceLifetime.Singleton); .

However, the mapping configuration instantiates a new resolver for each child regardless of the specified lifetime. What other options exist to efficiently convert a collection of parents where each child instance in the children sequence needs a hint that is only available at runtime on the destination parent?

public class SrcParent
{
    public int Id { get; set; }
    public List<SrcChild> SrcChildren { get; set; }
}

public class SrcChild
{
    public int Id { get; set; }
    public int SrcParentId { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

public class DstParent
{
    public int Id { get; set; }
    public int ConfigurationId { get; set; }
    public List<DstChild> DstChildren { get; set; }
}

public class DstChild
{
    public int Id { get; set; }
    public int DstParentId { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

this.CreateMap<SrcParent, DstParent>()
    .ForMember(dst => dst.Id, opt => opt.Ignore())
    .ForMember(dst => dst.ConfigurationId, opt => opt.Ignore())
    .ForMember(dst => dst.DstChildren, opt => opt.MapFrom<MyValueResolver>());

public class MyValueResolver : IValueResolver<SrcParent, DstParent, List<DstChild>>
{
    public List<DstChild> Resolve(SrcParent source, DstParent destination, List<DstChild> destMember, ResolutionContext context)
    {
        /*
         * Many expensive operations that can be safely cached
         * on the resolver instance through the lifetime.
         */
    }
}

// Seed the mapper with an existing instance to hint the child conversion.
var dst = new DstParent
{
    ConfigurationId = 42
};

this.mapper.Map(src, dst);

There is a MapFrom overload that takes a singleton resolver instance as parameter. Perhaps a cleaner way would be to simply extract that logic in a singleton service and inject that in the transient resolver service.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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