Got a mapper configuration which includes:
this.CreateMap<MyProp1, MyDesintationProp>();
this.CreateMap<MyProp2, MyDesintationProp>();
Then, inside the mapper for a more complex object, both these are used inside an inline ResolveUsing to merge into a list of MyDestinationProp:
.ForMember(dest => dest.MyDesintationPropList, opt => opt.ResolveUsing(tc =>
{
var results = new List<MyDesintationProp>();
if (tc.MyProp1 != null)
{
results.Add(Mapper.Map<MyDestinationProp>(tc.MyProp1));
}
if (tc.MyProp2 != null)
{
results.Add(Mapper.Map<MyDestinationProp>(tc.MyProp2));
}
return results;
}))
This works fine in production, but causes tests on this mapping to blow up, complaining
Property:
MyDestinationProp
---- System.InvalidOperationException : Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.
Which I guess makes sense because the mapper inside the mapper hasn't been initialised. But what's the best way to go about fixing this?
This is a very trivial example, that really doesn't need to use the context, cause it would also work with simple mappings.
public class Source
{
public string Name { get; set; }
public SourceChild Child { get; set; }
public override string ToString() => $"{typeof(Source)} -> {Name}";
}
public class Destination
{
public string Name { get; set; }
public DestinationChild Child { get; set; }
public override string ToString() => $"{typeof(Destination)} -> {Name}";
}
public class SourceChild
{
public string Name { get; set; }
public override string ToString() => $"{typeof(SourceChild)} -> {Name}";
}
public class DestinationChild
{
public string Name { get; set; }
public override string ToString() => $"{typeof(DestinationChild)} -> {Name}";
}
public class MappingContextProfile : Profile
{
public MappingContextProfile()
{
CreateMap<Source, Destination>()
.ForMember(source => source.Child, conf => conf.MapFrom((source, destination, destinationChild, context) =>
{
// Not really needed in this case, cause it does just some simple mapping.
// But if you would need to add some informations from outside
// (e.g. some interface mapping, etc)
// this would be the place without losing the magic of AutoMapper.
return context.Mapper.Map<DestinationChild>(source.Child);
}));
CreateMap<SourceChild, DestinationChild>();
}
}
public class MappingSimpleProfile : Profile
{
public MappingSimpleProfile()
{
CreateMap<Source, Destination>();
CreateMap<SourceChild, DestinationChild>();
}
}
public static class Program
{
public static async Task<int> Main(string[] args)
{
var config = new MapperConfiguration(cfg => cfg.AddProfile<MappingContextProfile>());
var mapper = config.CreateMapper();
var sources = Enumerable.Range(1, 10)
.Select(i => new Source { Name = $"{i}", Child = new SourceChild { Name = $"{i * 100}" } })
.ToList();
var destinations = mapper.Map<List<Destination>>(sources);
foreach (var item in destinations)
{
Console.WriteLine($"{item} -> {item.Child}");
}
return 0;
}
}
Related
I am trying to use AutoMapper to map a DTO to an Entity class but I keep getting an error.
Here is the DTO Class:
public class Product
{
public string ID { get; set; }
public string SKU { get; set; }
public string Name { get; set; }
public PriceTiers PriceTiers { get; set; }
}
and here is the Entity:
public partial class Product
{
public Product()
{
PriceTiers = new List<PriceTiers>();
}
[Key]
public string ID { get; set; }
public string SKU { get; set; }
public string Name { get; set; }
public virtual ICollection<PriceTiers> PriceTiers { get; set; }
}
Why do I keep getting the following error?
{"Missing type map configuration or unsupported
mapping.\r\n\r\nMapping types:\r\nPriceTiers ->
ICollection1\r\nWeb.Areas.DEAR.DTOs.PriceTiers -> System.Collections.Generic.ICollection1[[Web.Areas.DEAR.Data.PriceTiers,
Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]\r\n\r\n
Destination Member:\r\nPriceTiers\r\n"}
This is what I have in the Profile class:
AllowNullCollections = true;
CreateMap<DTOs.Product, Data.Product>();
CreateMap<DTOs.PriceTiers, Data.PriceTiers>();
and this is what I use to map the classes:
var products = _mapper.Map<IEnumerable<Product>>(result.Products);
This is what is in the Program.cs:
builder.Services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
The exception message is quite clear, the AutoMapper doesn't know how to map the data from DTOs.PriceTiers to ICollection<Data.PriceTiers>.
Solution 1: Map from DTOs.PriceTiers to ICollection<Data.PriceTiers>
I believe that Custom Type Converters is what you need.
Create Custom Type Converters.
public class ICollectionDataPriceTiersTypeConverter : ITypeConverter<DTOs.PriceTiers, ICollection<Data.PriceTiers>>
{
public ICollection<Data.PriceTiers> Convert(DTOs.PriceTiers src, ICollection<Data.PriceTiers> dest, ResolutionContext context)
{
if (src == null)
return default;
var singleDest = context.Mapper.Map<Data.PriceTiers>(src);
return new List<Data.PriceTiers>
{
singleDest
};
}
}
Add to mapping profile.
CreateMap<DTOs.PriceTiers, ICollection<Data.PriceTiers>>()
.ConvertUsing<ICollectionDataPriceTiersTypeConverter>();
Demo # .NET Fiddle
Solution 2: Map from ICollection<DTOs.PriceTiers> to ICollection<Data.PriceTiers>
If the PriceTiers in DTOs.Product supports multiple items and mapping with many to many (to ICollection<Data.ProductTiers>), then consider modifying the property as the ICollection<DTOs.PriceTiers> type.
namespace DTOs
{
public class Product
{
...
public ICollection<PriceTiers> PriceTiers { get; set; }
}
}
Did you added "CreateMapper()" method after your configurations?
Try something like that.
public class MappingProfile : Profile
{
public MappingProfile {
AllowNullCollections = true;
CreateMap<DTOs.Product, Data.Product>();
CreateMap<DTOs.PriceTiers, Data.PriceTiers>();
}
}
After that, on your container service, inject this dependency:
var mappingConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
builder.Services.AddSingleton(mapper);
After some more research I found out that my mapping profile was not in the right order. These are the changes I made.
public class AutoMapperProfiles : Profile
{
public AutoMapperProfiles()
{
AllowNullCollections = true;
CreateMap<DTOs.PriceTiers, Data.PriceTiers>();
CreateMap<DTOs.Product, Data.Product>()
.ForMember(dto => dto.PriceTiers, opt => opt.MapFrom(x => x.PriceTiers));
}
}
Now it maps perfectly
I'm new to AutoMapper and trying to map Array class ItemLink[].
public class ViewModel
{
public ItemLink[] ItemLinks { get; set; }
}
public class ItemLink
{
public string Description { get; set; }
}
I tried:
Mapper.Map<viewModel.ItemLink>(db.ItemLinks);
Error:
"Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance."
Can't it be simple mapping?
EDIT 1
To clarify more, I'm getting similar class structure from database. Example,
public class Db
{
public ItemLink[] ItemLinks { get; set; }
}
So, I want to map ViewModel.ItemLink[] with Db.ItemLink[].
You cannot provide variable to a generic parameter like you do in Mapper.Map<viewModel.ItemLink>(db.ItemLinks);. It is called Type parameter and must be a type.
As #gisek mentioned in his answer you need to configure mapper first. Normally it is done at application startup.
You can consider to fetch full objects from db, but you also have an option to use Queryable Extensions which are there to only fetch data you need for your view model.
The configuration. I assume that you have namespace DB for entity in database, and View namespace for view model.
Mapper.Initialize(cfg => {
cfg.CreateMap<DB.ItemLink, View.ItemLink>();
});
Mapper.Configuration.AssertConfigurationIsValid();
Fetch full entity from DB and then map it to property:
var viewModel = new View.Item();
viewModel.ItemLinks = Mapper.Map<View.ItemLink[]>(db.ItemLinks.ToArray());
Project entity from DB to view model:
var viewModel = new View.Item();
viewModel.ItemLinks = db.ItemLinks.ProjectTo<View.ItemLink>().ToArray();
I assumed you are using .net mvc
Firstly you need Initialize your mapping on Application Start, there is no need to initialize every time in your controller etc.
Following error means you didn't initialize mapper, automapper doesn't know your source and destination object.
Error:
"Mapper not initialized. Call Initialize with appropriate
configuration. If you are trying to use mapper instances through a
container or otherwise, make sure you do not have any calls to the
static Mapper.Map methods, and if you're using ProjectTo or
UseAsDataSource extension methods, make sure you pass in the
appropriate IConfigurationProvider instance."
For Solution:
Create an AutoMapperConfig object in your App_Start folder.
public class AutoMapperConfig
{
public static void Register()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<source,destination>(); /*If source and destination object have same propery */
cfg.CreateMap<source, destination>()
.ForMember(dest => dest.dId, opt => opt.MapFrom(src => src.sId)); /*If source and destination object haven't same property, you need do define which property refers to source property */
});
}
}
In your Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutoMapperConfig.Register(); // Call Register method on App_Start
}
In your controller
var mappedArray = Mapper.Map<viewmodel.ItemLink[]>(db.ItemLinks);
or
var mappedArray = Mapper.Map<viewmodel.ItemLink[],ItemLinks[]>(db.ItemLinks); //ItemLinks[] refers to your dto.
You need to configure the mapper first.
There are 2 possible approaches, static and non-static. I lean towards non-static as it allows you to create multiple mappers, which can use different mapping strategies.
Non-static example:
using AutoMapper;
namespace Experiments
{
class Program
{
static void Main(string[] args)
{
var links = new ItemLink[]
{
new ItemLink {Description = "desc 1"},
new ItemLink {Description = "desc 2"},
};
var item = new Item
{
ItemLinks = links,
};
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ItemLink, ItemLink>(); // you can extend this part of the configuration here
cfg.CreateMap<Item, Item>();
cfg.CreateMap<ItemLink, MyCustomClass>()
.ForMember(myCustomClass => myCustomClass.DescriptionWithDifferentName,
expression => expression.MapFrom(itemLink => itemLink.Description)); // to map to a different type
// more configs can do here
// e.g. cfg.CreateMap<Item, SomeOtherClass>();
});
IMapper mapper = new Mapper(config);
ItemLink linkClone = mapper.Map<ItemLink>(links[0]);
ItemLink[] linkArrayClone = mapper.Map<ItemLink[]>(item.ItemLinks);
Item itemClone = mapper.Map<Item>(item);
MyCustomClass myCustomClassObject = mapper.Map<MyCustomClass>(links[0]);
}
}
public class Item
{
public ItemLink[] ItemLinks { get; set; }
}
public class ItemLink
{
public string Description { get; set; }
}
public class MyCustomClass
{
public string DescriptionWithDifferentName { get; set; }
}
}
Static example:
using AutoMapper;
namespace Experiments
{
class Program
{
static void Main(string[] args)
{
var links = new ItemLink[]
{
new ItemLink {Description = "desc 1"},
new ItemLink {Description = "desc 2"},
};
var item = new Item
{
ItemLinks = links,
};
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ItemLink, ItemLink>(); // you can extend this part of the configuration here
cfg.CreateMap<Item, Item>();
cfg.CreateMap<ItemLink, MyCustomClass>()
.ForMember(myCustomClass => myCustomClass.DescriptionWithDifferentName,
expression => expression.MapFrom(itemLink => itemLink.Description));
// to map to a different type
// more configs can do here
// e.g. cfg.CreateMap<Item, SomeOtherClass>();
});
ItemLink linkClone = Mapper.Map<ItemLink>(links[0]);
ItemLink[] linkArrayClone = Mapper.Map<ItemLink[]>(item.ItemLinks);
Item itemClone = Mapper.Map<Item>(item);
MyCustomClass myCustomClassObject = Mapper.Map<MyCustomClass>(links[0]);
}
public class Item
{
public ItemLink[] ItemLinks { get; set; }
}
public class ItemLink
{
public string Description { get; set; }
}
public class MyCustomClass
{
public string DescriptionWithDifferentName { get; set; }
}
}
}
You can also configure Automapper to create missing maps automatically with cfg.CreateMissingTypeMaps = true;
using AutoMapper;
namespace Experiments
{
class Program
{
static void Main(string[] args)
{
var links = new ItemLink[]
{
new ItemLink {Description = "desc 1"},
new ItemLink {Description = "desc 2"},
};
var item = new Item
{
ItemLinks = links,
};
Mapper.Initialize(cfg =>
{
// now AutoMapper will try co create maps on it's own
cfg.CreateMissingTypeMaps = true;
// we can still add custom maps like that
cfg.CreateMap<ItemLink, MyCustomClass>()
.ForMember(myCustomClass => myCustomClass.DescriptionWithDifferentName,
expression => expression.MapFrom(itemLink => itemLink.Description));
});
ItemLink linkClone = Mapper.Map<ItemLink>(links[0]);
ItemLink[] linkArrayClone = Mapper.Map<ItemLink[]>(item.ItemLinks);
Item itemClone = Mapper.Map<Item>(item);
// without custom map myCustomClassObject.DescriptionWithDifferentName would be null
MyCustomClass myCustomClassObject = Mapper.Map<MyCustomClass>(links[0]);
}
public class Item
{
public ItemLink[] ItemLinks { get; set; }
}
public class ItemLink
{
public string Description { get; set; }
}
public class MyCustomClass
{
public string DescriptionWithDifferentName { get; set; }
}
}
}
I am not sure that I understood what you need,
I guess that you are trying to map from a list of ItemLink to a list of viewModel.ItemLink
so Mapper.Map<viewModel.ItemLink>(db.ItemLinks);
become
var listOfViewModelItemLink = Mapper.Map<List<viewModel.ItemLink>>(db.ItemLinks);
you can call ToArray() on listOfViewModelItemLink then assign to ItemLinks property of Item class
I am not sure but I guess that you are trying to map from an array of ItemLink to an array of viewModel.ItemLink. You should do it like this:
var viewModels = db.ItemLinks
.ToArray()
.Select(x=>Mapper.Map<viewModel.ItemLink>(x))
.ToArray();
Given the following:
public class Foo
{
public Int32 Foo_PK { get; set; }
public String SomeProperty { get; set; }
}
public class Bar
{
public Int32 Bar_PK { get; set; }
public Int32 Foo_FK { get; set; }
public String SomeOtherProperty { get; set; }
}
public class JoinResult<TEntity, TJoiningEntity>
{
public TEntity From { get; private set; }
public TEntity To { get; private set; }
public JoinResult(TEntity from, TEntity to)
{
this.From = from;
this.To = to;
}
}
public interface IFooResult
{
public String SomeProperty { get; set; }
}
public interface IBarResult : IFooResult
{
public String SomeOtherProperty { get; set; }
}
public class FooResultDTO : IFooResult, IBarResult
{
public String SomeProperty { get; set; }
public String SomeOtherProperty { get; set; }
}
The idea behind this is that we some method of dispensing foo's and foo's with other related records, e.g. if there are 4 bar's then 4 rows in a table with the additional fields.
public class FooDispensary
{
public IQueryable<T> Dispense<T>()
where T: IFooResult
{
using (var repository = new Repository())
{
// TODO: Handle mapping for Foo -> FooResult
// Project to
return repository.Foos.ProjectTo<FooResultDTO>();
}
}
public IQueryable<T> DispenseWithBars<T>()
where T : IFooResult, IBarResult
{
using (var repository = new Repository())
{
// TODO: Handle mapping for JoinResult.From (same as Foo -> FooResult) as well as to JoinResult.To
// Project to
return repository.Foos.Join((f) => f.Foo_PK,
(b) => b.Foo_FK,
(f, b) => new JoinResult<Foo, Bar>(f, b))
.ProjectTo<FooResultDTO>();
}
}
}
However, I would ideally like to only specify the base mapping once (Foo -> IFooResult) and then re-use this in the methods where we need to join to a child table.
There are multiple reasons behind wanting to do this which are specific to my project however no need to go into them, I am just wondering if this is possible as I have struggled with the syntax thus far?
Thanks
Create a Map between Foo and FooResult. Because the Property SomeProperty is named the same in both the source and target Automapper will be able to figure out the mapping implicitly.
// TODO: Handle mapping for Foo -> FooResult
AutoMapper.Mapper.CreateMap<Foo, FooResult>();
Then create a map between JoinResult<Foo, Bar> and FooResultDTO
// TODO: Handle mapping for JoinResult.From (same as Foo -> FooResult) as well as to JoinResult.To
AutoMapper.Mapper.CreateMap<JoinResult<Foo, Bar>, FooResultDTO>()
.ForMember(r => r.SomeProperty, opt => opt.MapFrom(f => f.From.SomeProperty)
.ForMember(r => r.SomeOtherProperty, opt => opt.MapFrom(f => f.To.SomeOtherProperty)
However, I would ideally like to only specify the base mapping once (Foo -> IFooResult) and then re-use this in the methods where we need to join to a child table.
You're not resusing the mapping between Foo and IFooResult anywhere in your example. Your second function needs to map between JoinResult<Foo, Bar> and FooResultDTO as shown above. If you need to reuse mappings I suggest you look into using an AutoMapper Profile and managing a singleton AutoMapper instance that can be shared between your functions: https://github.com/AutoMapper/AutoMapper/wiki/Configuration
I am new of ASP.NET BoilerPlate (ABP) and I am trying to understand how to create custom mappings using AutoMapper and, maybe, the ABP automapper attributes: AutoMap, AutoMapFrom, AutoMapTo.
With ABP I can map two classes in this way:
[AutoMapTo(typeof(DestClass)]
public class SourceClass {
public string A { get; set; }
public string B { get; set; }
}
public class DestClass {
public string A { get; set; }
public string B { get; set; }
}
But if I have two classes like the following where I want the property AB to be automapped as a join of A and B:
[AutoMapTo(typeof(DestClass)]
public class SourceClass {
public string A { get; set; }
public string B { get; set; }
}
public class DestClass {
public string AB { get; set; }
}
Are there some attributes with ABP? Or do I need to use the "classical" AutoMapper code:
Mapper.CreateMap<SourceClass, DestClass>()
.ForMember(dest => dest.AB,
opts => opts.MapFrom(src => (src.A + ", " + src.B)));
And where do I have to place such init code?
I found a solution I share here.
In "MyProject.Application" project I defined my automapper customs (I used profiles):
public class MyProjectAutoMapperProfile : AutoMapper.Profile {
protected override void Configure() {
CreateMap<SourceClass, DestClass>()
.ForMember(dest => dest.AB,
opts => opts.MapFrom(src => (src.A + ", " + src.B)));
// other customs here...
}
Then I registered it for injection in the Initialize method of the class MyProjectApplicationModule:
[DependsOn(typeof(MyProjectCoreModule), typeof(AbpAutoMapperModule))]
public class MyProjectApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
// --- MY CODE for registering custom automapping
var mapperConfiguration = new MapperConfiguration(cfg => {
cfg.AddProfile(new MyProjectMapperProfile()); // <= here my custom mapping
});
var mapper = mapperConfiguration.CreateMapper();
IocManager.IocContainer.Register(
Castle.MicroKernel.Registration.Component.For<IMapper>().Instance(mapper)
);
// --- MY CODE
}
}
Note that I directly used the Castle IOC register methods because I did not find any useful registering method for objects in ABP. Do you know one?
Finally I used my custom mapping as injection in my Application Service and used it directly:
public class MyAppService : MyNewHouseAppServiceBase, IMyAppService {
// ...
public MyAppService(IRepository<SourceClass, long> myRepository, AutoMapper.IMapper mapper) {
_myRepo = myRepository;
_mapper = mypper;
}
public async Task<DestClass> GetSource(long id) {
var source = await _myRepo.Find(id);
// USE THE INJECTED MAPPER
return _mapper.Map<DestClass>(source);
}
public async Task<ListResultOutput<DestClass>> GetSources() {
var sources = await _myRepo.GetAllListAsync();
return new ListResultOutput<DestClass>(
// USE THE INJECTED MAPPER
_mapper.Map<List<DestClass>>(sources)
);
}
}
No need to list all the customer mapping on the Module. Just tell the module to find all the classes which extend AutoMapper.Profile:
Assembly thisAssembly = typeof(AbpProjectNameApplicationModule).GetAssembly();
IocManager.RegisterAssemblyByConvention(thisAssembly);
cfg.AddProfiles(thisAssembly);
I've just started with AutoMapper in C#. I've succesfully created a mapping like this:
Mapper.CreateMap<InputTypeA, OutputTypeA>()
I've also found a way to add some logic to specific properties, like formatting a date (in InputTypeA) to a string in a specific format (in OutputTypeA).
.ForMember(
dest => dest.MyDateProperty,
opt => opt.ResolveUsing(
src => String.Format("{0:yyyy-MM-dd}", src.MyDateProperty)));
Now I need to do the same for a number of float properties, but I'm wondering if there is a short/easy way to do this, except copying a piece of code like the one above for every property that needs to follow this rule.
I've found that I can create a new map like this for mapping floats to strings:
Mapper.CreateMap<float,string>()
.ConvertUsing(src =>
String.Format(CultureInfo.InvariantCulture.NumberFormat, "{0:0.00}", src));
This works, but is too generic, because I also have a mapping for another type (let's call it InputTypeB), that also contains float properties, which need to be treated differently.
Mapper.CreateMap<InputTypeB, OutputTypeB>()
How can I make the float-to-string mapping part of the first mapping only?
You could create two separate mappers based on two separate configurations, only one of which includes the float-to-string mapping:
public class InputTypeA { public float Foo { get; set; } }
public class OutputTypeA { public string Foo { get; set; } }
public class InputTypeB { public float Bar { get; set; } }
public class OutputTypeB { public string Bar { get; set; } }
public class Program
{
public static void Main(string[] args)
{
Func<float, string> mapFunc =
src => String.Format(CultureInfo.InvariantCulture.NumberFormat, "{0:0.00}", src);
var floatToStringConfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<InputTypeA, OutputTypeA>();
cfg.CreateMap<float, string>().ConvertUsing(mapFunc);
});
var regularConfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<InputTypeB, OutputTypeB>();
});
IMapper floatToStringMapper = floatToStringConfig.CreateMapper();
IMapper regularMapper = regularConfig.CreateMapper();
var aIn = new InputTypeA() { Foo = 1f };
var aOut = floatToStringMapper.Map<OutputTypeA>(aIn);
Console.WriteLine(aOut.Foo); // prints "1.00"
var bIn = new InputTypeB() { Bar = 1f };
var bOut = regularMapper.Map<OutputTypeB>(bIn);
Console.WriteLine(bOut.Bar); // prints "1"
}
}
You can create custom value resolvers for each case you need to handle. Then apply these to the appropriate members in your mappings.
As an example, I need to map from TypeA to TypeB, I only want DateB to use the custom conversion:
public class TypeA {
public DateTime DateA { get; set; }
public DateTime DateB { get; set; }
}
public class TypeB {
public string DateA { get; set; }
public string DateB { get; set; }
}
I create a custom resolver:
class DateStringResolver : ValueResolver<DateTime, string> {
protected override string ResolveCore(DateTime source) {
return String.Format("{0:yyyy-MM-dd}", source);
}
}
Then in my mapper config:
Mapper.CreateMap<TypeA, TypeB>()
//Only Date B will use our custom resolver
.ForMember(d => d.DateB, opt => opt.ResolveUsing<DateStringResolver>().FromMember(src => src.DateA));
The resolver can now be applied wherever it is needed.
Docs:https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers