Create a MapperConfiguration
instance and initialize configuration via the constructor:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Foo, Bar>();
cfg.AddProfile<FooProfile>();
});
The MapperConfiguration
instance can be stored statically, in a static field or in a dependency injection container. Once created it cannot be changed/modified.
var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<Foo, Bar>();
cfg.AddProfile<FooProfile>();
});
Starting with 9.0, the static API is no longer available.
A good way to organize your mapping configurations is with profiles.
Create classes that inherit from Profile
and put the configuration in the constructor:
// This is the approach starting with version 5
public class OrganizationProfile : Profile
{
public OrganizationProfile()
{
CreateMap<Foo, FooDto>();
// Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
}
}
// How it was done in 4.x - as of 5.0 this is obsolete:
// public class OrganizationProfile : Profile
// {
// protected override void Configure()
// {
// CreateMap<Foo, FooDto>();
// }
// }
In earlier versions the Configure
method was used instead of a constructor.
As of version 5, Configure()
is obsolete. It will be removed in 6.0.
Configuration inside a profile only applies to maps inside the profile. Configuration applied to the root configuration applies to all maps created.
Profiles can be added to the main mapper configuration in a number of ways, either directly:
cfg.AddProfile<OrganizationProfile>();
cfg.AddProfile(new OrganizationProfile());
or by automatically scanning for profiles:
// Scan for all profiles in an assembly
// ... using instance approach:
var config = new MapperConfiguration(cfg => {
cfg.AddMaps(myAssembly);
});
var configuration = new MapperConfiguration(cfg => cfg.AddMaps(myAssembly));
// Can also use assembly names:
var configuration = new MapperConfiguration(cfg =>
cfg.AddMaps(new [] {
"Foo.UI",
"Foo.Core"
});
);
// Or marker types for assemblies:
var configuration = new MapperConfiguration(cfg =>
cfg.AddMaps(new [] {
typeof(HomeController),
typeof(Entity)
});
);
AutoMapper will scan the designated assemblies for classes inheriting from Profile and add them to the configuration.
You can set the source and destination naming conventions
var configuration = new MapperConfiguration(cfg => {
cfg.SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
cfg.DestinationMemberNamingConvention = new PascalCaseNamingConvention();
});
This will map the following properties to each other:
property_name -> PropertyName
You can also set this at a per profile level
public class OrganizationProfile : Profile
{
public OrganizationProfile()
{
SourceMemberNamingConvention = new LowerUnderscoreNamingConvention();
DestinationMemberNamingConvention = new PascalCaseNamingConvention();
//Put your CreateMap... Etc.. here
}
}
If you don't need a naming convention, you can use the ExactMatchNamingConvention
.
You can also replace individual characters or entire words in source members during member name matching:
public class Source
{
public int Value { get; set; }
public int Ävíator { get; set; }
public int SubAirlinaFlight { get; set; }
}
public class Destination
{
public int Value { get; set; }
public int Aviator { get; set; }
public int SubAirlineFlight { get; set; }
}
We want to replace the individual characters, and perhaps translate a word:
var configuration = new MapperConfiguration(c =>
{
c.ReplaceMemberName("Ä", "A");
c.ReplaceMemberName("í", "i");
c.ReplaceMemberName("Airlina", "Airline");
});
Sometimes your source/destination properties will have common pre/postfixes that cause you to have to do a bunch of custom member mappings because the names don't match up. To address this, you can recognize pre/postfixes:
public class Source {
public int frmValue { get; set; }
public int frmValue2 { get; set; }
}
public class Dest {
public int Value { get; set; }
public int Value2 { get; set; }
}
var configuration = new MapperConfiguration(cfg => {
cfg.RecognizePrefixes("frm");
cfg.CreateMap<Source, Dest>();
});
configuration.AssertConfigurationIsValid();
By default AutoMapper recognizes the prefix "Get", if you need to clear the prefix:
var configuration = new MapperConfiguration(cfg => {
cfg.ClearPrefixes();
cfg.RecognizePrefixes("tmp");
});
By default, AutoMapper tries to map every public property/field. You can filter out properties/fields with the property/field filters:
var configuration = new MapperConfiguration(cfg =>
{
// don't map any fields
cfg.ShouldMapField = fi => false;
// map properties with a public or private getter
cfg.ShouldMapProperty = pi =>
pi.GetMethod != null && (pi.GetMethod.IsPublic || pi.GetMethod.IsPrivate);
});
By default, AutoMapper only recognizes public members. It can map to private setters, but will skip internal/private methods and properties if the entire property is private/internal. To instruct AutoMapper to recognize members with other visibilities, override the default filters ShouldMapField and/or ShouldMapProperty :
var configuration = new MapperConfiguration(cfg =>
{
// map properties with public or internal getters
cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
cfg.CreateMap<Source, Destination>();
});
Map configurations will now recognize internal/private members.
Because expression compilation can be a bit resource intensive, AutoMapper lazily compiles the type map plans on first map. However, this behavior is not always desirable, so you can tell AutoMapper to compile its mappings directly:
var configuration = new MapperConfiguration(cfg => {});
configuration.CompileMappings();
For a few hundred mappings, this may take a couple of seconds.