Automapper - Convert UTC to Specific timezone

Viewed 977

I have the following which when translating DateUtc from source to dest Date, I want to apply a conversion. Now the following converter I wrote will work for a specific field because that is specified.

I would like my converter to be more flexible that I can pass the other object than SourceDto1, DestDto1 such as SourceDto2 and DestDto2

public class SourceDto1
{
   public DateTime DateUtc {get;set;}
}
public class DestDto1
{
   public DateTime Date {get;set;}
}
public class SourceDto2
{
   public DateTime DateUtc {get;set;}
}
public class DestDto2
{
   public DateTime Date {get;set;}
}

converter

public class AttachmentCreatedDateResolver : IValueResolver<SourceDto1, DestDto1 DateTime>
    {

        private readonly Settings _settings;
        public AttachmentCreatedDateResolver(Settings settings)
        {
            _settings = settings;
        }


        public DateTime Resolve(SourceDto1 source, DestDto1 destination, DateTime destMember, ResolutionContext context)
        {
            TimeZoneInfo tzi = TZConvert.GetTimeZoneInfo(_settings.TimeZone);
            var converted = TimeZoneInfo.ConvertTimeFromUtc(source.DateUtc, tzi);
            return converted;
        }
    }

I guess i dont want to create a different resolver class for every pair of objects I have that I need to convert dates between properties.

ITypeConverter might work but I was not sure how to inject my Settings from DI

1 Answers

You can create an implementation of IMemberValueResolver for this:

public class AttachmentCreatedDateResolver : IMemberValueResolver<object, object, DateTime, DateTime>
{
    private readonly Settings _settings;
    public AttachmentCreatedDateResolver(Settings settings)
    {
        _settings = settings;
    }

    public DateTime Resolve(object source, object destination, DateTime sourceMember, DateTime destMember, ResolutionContext context)
    {
        TimeZoneInfo tzi = TZConvert.GetTimeZoneInfo(_settings.TimeZone);
        var converted = TimeZoneInfo.ConvertTimeFromUtc(sourceMember, tzi);
        return converted;
    }
}

This behaves similar to an implementation of IValueResolver, allowing you to inject dependencies into the resolver while also allowing you to use it at the member level for any object (note that the source and destination types are set to object). You'd then be able to configure this same resolver for each type mapping with something like:

CreateMap<SourceDto1, DestDto1>()
    .ForMember(d => d.Date, opt => opt.MapFrom<AttachmentCreatedDateResolver, DateTime>(s => s.DateUtc));
CreateMap<SourceDto2, DestDto2>()
    .ForMember(d => d.Date, opt => opt.MapFrom<AttachmentCreatedDateResolver, DateTime>(s => s.DateUtc));
Related