Conditional Object Mapper
Conditional Object Mappers make new type maps based on conditional between the source and the destination type.
var config = new MapperConfiguration(cfg => {
cfg.AddConditionalObjectMapper().Where((s, d) => s.Name == d.Name + "Dto");
});
Member Configuration
Member Configuration is like Configuration but you can have complete control on what is and isn't used.
var config = new MapperConfiguration(cfg => { cfg.AddMemberConfiguration(); });
AddMemberConfiguration() starts off with a blank slate. Everything that applies in Configuration by default is gone to start with.
Naming Conventions
AddMemberConfiguration().AddMember<NameSplitMember>()
gets you default naming convention functionality.
Can overwrite the source and destination member naming conventions by passing a lambda through the parameter.
SourceExtentionMethods can also be set here.
If you don't set anything AutoMapper will use DefaultMember, which will only check using the Name of the property.
PS: If you don't set this Flattening of objects will be disabled.
Replacing characters
AddMemberConfiguration().AddName<ReplaceName>(_ => _.AddReplace("Ä", "A").AddReplace("í", "i"));
Recognizing pre/postfixes
AddMemberConfiguration().AddName<PrePostfixName>(_ => _.AddStrings(p => p.Prefixes, "Get", "get").AddStrings(p => p.DestinationPostfixes, "Set"));
Attribute Support
AddMemberConfiguration().AddName<SourceToDestinationNameMapperAttributesMember>();
*Currently is always on
Looks for instances of SourceToDestinationMapperAttribute for Properties/Fields and calls user defined isMatch function to find member matches.
MapToAttribute is one of them which will match the property based on name provided.
public class Foo
{
[MapTo("SourceOfBar")]
public int Bar { get; set; }
}
Getting AutoMapper Defaults
AddMemberConfiguration().AddMember<NameSplitMember>().AddName<PrePostfixName>(_ => _.AddStrings(p => p.Prefixes, "Get"))
Is the default values set by Configuration if you don't use AddMemberConfiguration().
Expand-ability
Each of the AddName and AddMember types are based on an interface ISourceToDestinationNameMapper and IChildMemberConfiguration. You can make your own classes off the interface and configure their properties through the lambda statement argument, so you can have fine tune control over how AutoMapper resolves property maps.
Multiple Configurations
Each configuration is its own set of rules that all must pass in order to say a property is mapped. If you make multiple configurations they are completely separate from one another.
Profiles
These can be added to Profile as well as the ConfigurationStore.
Each Profiles rules are separate from one another, and won't share any conditions.
If a map is generated from AddConditionalObjectMapper of one profile, the AddMemberConfigurations of only that profile can be used to resolve the property maps.
Example
Shown below is two profiles for making conventions for transferring to and from a Data Transfer Object.
Each one is isolated to one way of the mappings, and the rules are explicitly stated for each side.
// Flattens with NameSplitMember
// Only applies to types that have same name with destination ending with Dto
// Only applies Dto post fixes to the source properties
public class ToDTO : Profile
{
protected override void Configure()
{
AddMemberConfiguration().AddMember<NameSplitMember>().AddName<PrePostfixName>(
_ => _.AddStrings(p => p.Postfixes, "Dto"));
AddConditionalObjectMapper().Where((s, d) => s.Name == d.Name + "Dto");
}
}
// Doesn't Flatten Objects
// Only applies to types that have same name with source ending with Dto
// Only applies Dto post fixes to the destination properties
public class FromDTO : Profile
{
protected override void Configure()
{
AddMemberConfiguration().AddName<PrePostfixName>(
_ => _.AddStrings(p => p.DestinationPostfixes, "Dto"));
AddConditionalObjectMapper().Where((s, d) => d.Name == s.Name + "Dto");
}
}