In previous versions of AutoMapper I created a general purpose PreCondition to conditionally map/not map certain members. I achieved this by adding an array of member names to the Map options and checking this list against the member currently being mapped as demonstrated in the code below.
Unfortunately MemberName is no longer exposed in ResolutionContext so I have no idea what member is currently being mapped. I could not find anything in the new slimmed down ResolutionContext that would lead me to this information.
I know I can write lots of specific PreCondition cases but I'm using this for zillions of types. Does anyone know of some other means of obtaining the current MemberName?
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
public class AutoMapperTest
{
public class SomeSourceType
{
public string String1;
public string String2;
public string String3;
}
public class SomeDestinationType
{
public string String1;
public string String2;
public string String3;
}
public void Test()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SomeSourceType, SomeDestinationType>();
cfg.ForAllMaps((Action<TypeMap, IMappingExpression>)((typeMap, map) =>
{
map.ForAllMembers(opt =>
{
opt.PreCondition(context =>
{
var optionsItems = context.Options.Items;
var propertiesToMap = (IEnumerable<string>)(optionsItems.Keys.Contains("PropertiesToMap") ? optionsItems["PropertiesToMap"] : null);
// The following line no longer works because MemberName is no longer exposed!
return (propertiesToMap == null) || propertiesToMap.Contains(context.MemberName);
});
});
}));
});
var source = new SomeSourceType() { String1 = "Hello", String2 = "World" };
// This will map ALL properties.
var dest = Mapper.Map<SomeSourceType, SomeDestinationType>(source);
// This will only map String1 and String3.
dest = Mapper.Map<SomeSourceType, SomeDestinationType>(source, opts => opts.Items.Add("PropertiesToMap", new string[] { "String1", "String3" }));
}
}
You were almost there. The "opt" parameter is type IMemberConfigurationExpression
, which includes the destination member as a property. Here's your updated example:
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
public class AutoMapperTest
{
public class SomeSourceType
{
public string String1;
public string String2;
public string String3;
}
public class SomeDestinationType
{
public string String1;
public string String2;
public string String3;
}
public void Test()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SomeSourceType, SomeDestinationType>();
cfg.ForAllMaps((Action<TypeMap, IMappingExpression>)((typeMap, map) =>
{
map.ForAllMembers(opt =>
{
opt.PreCondition(context =>
{
var optionsItems = context.Options.Items;
var propertiesToMap = (IEnumerable<string>)(optionsItems.Keys.Contains("PropertiesToMap") ? optionsItems["PropertiesToMap"] : null);
return (propertiesToMap == null) || propertiesToMap.Contains(opt.DestinationMember.Name);
});
});
}));
});
var source = new SomeSourceType() { String1 = "Hello", String2 = "World" };
var dest = Mapper.Map<SomeSourceType, SomeDestinationType>(source);
dest = Mapper.Map<SomeSourceType, SomeDestinationType>(source, opts => opts.Items.Add("PropertiesToMap", new string[] { "String1", "String3" }));
}
}