简体   繁体   中英

Automapper custom value resolver reuse for multiple types

I have a project which I am trying to use AutoMapper to map from multiple classes in each of these classes there are properties where I would like to use some custom logic to parse the source value to the destination. I have tried to use custom resolver methods as documented on the AutoMapper docs.

Here is my code:

public class CustomDateTextHandler : IValueResolver<object, object, string>
{
    public string Resolve(object source, object destination, string destMember, ResolutionContext context)
    {
        string txt = source.ToString();
        txt.Replace("AM/PM", "tt");
        txt.Replace("HH:MM", "hh:mm");
        if (txt.Contains("format"))
        {
            txt.Replace("mmm", "MMM");
        }
        return txt;
    }
}

public class SMapping : Profile
{
    public SMapping()
    {
        CreateMap<SourceForm, s_form>()
            .ForMember(dest => dest.id, opt => opt.Ignore())
            .ForMember(dest => dest.cell_text, opt => opt.MapFrom<CustomDateTextHandler>())
            .ForMember(dest => dest.fn_def, opt => opt.MapFrom<CustomCodeTextResolver>());
    }

What I am trying to get is the cell_text value processed with my replace logic in the resolver method but the issue I am facing is that what is being passed to the resolver is the entire SMapping instance, I would like to be able to reuse the resolver code across different classes where the property names will be different, however looking at what it going on at the moment I could not really use the resolver code across my different classes.

Can someone help me?

Thank you in advance.

Use IMemberValueResolver instead of IValueResolver.
Compared to IValueResolver, its Resolve function gets one more parameter: value.
Registering mapping with IMemberValueResolver requires you to pass 1 extra parameter - not the 'value' directly, but a lambda that will produce a 'value' from given source object.

public class CustomDateTextHandler :
    IMemberValueResolver< // note: different interface
        object, object,
        string, string   // note: 1 more parameter
    >
{
    public string Resolve(
        object source, object destination,
        string sourceValue, string destMember, // note: 1 more parameter
        ResolutionContext context
    )
    {
        // here, see the difference:
        // source - source object, whole
        // sourceMember - value produced by extra lambda passed in mapping
    }
}

public class SMapping : Profile
{
    public SMapping()
    {
        CreateMap<SourceForm, s_form>()
            ...
            .ForMember(
                dest => dest.cell_text,
                opt => opt.MapFrom<CustomDateTextHandler, string>(source => source.PROPERTY11)) // note: this produces that sourceValue
            
            .ForMember(
                dest => dest.fn_def,
                opt => opt.MapFrom<CustomCodeTextResolver, string>(source => source.PROPERTY22)); // note: this produces that sourceValue
            
    }

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