Tuesday, July 14, 2020

[AutoMapper] Custom Type and Value converter


 .NET Core   .NET   AutoMapper 


▌Introduction


We can implement the following AutoMapper’s interface to customize the Type or Value converter:


This article will show a few samples for how to use them.


▌Environment


▋AutoMapper 8.0.0


▌Implement


We are going to convert a MyClass1 object to MyClas2 object, that the classes are like following,


▋MyClass1

public class MyClass1 {
        public string Amount { get; set; }
        public string PayDate { get; set; }
        public string PayTime { get; set; }
    }


▋MyClass2

public class MyClass2 {
        public decimal Amount { get; set; }
        public DateTime PayOn { get; set; }
    }



▋ ITypeConverter

If the source and destination classes have too many differences to map their properties, we can implement ITypeConverter to put all the convert logic inside.


public class MyConverter : ITypeConverter<MyClass1, MyClass2>
{
    public DtoMerchantCreation Convert(MyClass1 source, MyClass2 destination, ResolutionContext context)
    {
        // Convert MyClass1 instance to MyClass2
    }
}


Usage:

var configuration = new MapperConfiguration(cfg => {
                cfg.CreateMap<MyClass1, MyClass2>().ConvertUsing<MyConverter>();
            });




▋ IValueConverter


Implement IValueConverter if the destination property’s value comes from a single property of the source.



public class AmountConverter : IValueConverter<string, decimal>
{
    public decimal Convert(string sourceMember, ResolutionContext context)
    {
         // Convert string to decimal
    }
}


Usage:

var configuration = new MapperConfiguration(cfg => {
        cfg.CreateMap<MyClass1, MyClass2>()
                    .ForMember(dest => dest.Amount, opt => opt.ConvertUsing(new AmountConverter()));

});



▋ IValueResolver


Implement IValueResolver if the destination property’s value comes from multiple properties of the source.



public class PayOnResolver : IValueResolver<MyClass1, MyClass2, DateTime>
{
    public DateTime Resolve(MyClass1 source, MyClass2 destination, DateTime destMember, ResolutionContext context)
    {
        string dateTimeStr = $"{source.PayDate} {source.PayTime}+08:00"; // e.q. "2020-03-10 08:00:00+08:00"
        return Convert.ToDateTime(dateTimeStr);
    }
}


Usage:

var configuration = new MapperConfiguration(cfg => {
        cfg.CreateMap<MyClass1, MyClass2>()
                    .ForMember(dest => dest.PayOn, opt => 
                               opt.MapFrom<PayOnResolver>())
});



Notice that if we have the other class: MyClassA, which inherits MyClass1

public class MyClassA : MyClass1 {
    }

Then it can also reuse the PayOnResolver as well. For example,

var configuration = new MapperConfiguration(cfg => {
        cfg.CreateMap<MyClassA, MyClass2>()
                    .ForMember(dest => dest.PayOn, opt => 
                               opt.MapFrom<PayOnResolver>())
});



▌Reference








No comments:

Post a Comment