Examples
Every example below is executed and asserted against the real library before publishing — none of these are hypothetical.
1. Basic mapping
Same-named, same-type properties are mapped automatically — no configuration beyond CreateMap.
public class SimpleSource
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
public class SimpleDestination
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
var config = new MapperConfig();
config.CreateMap<SimpleSource, SimpleDestination>();
IMapper mapper = new Mapper(config);
var result = mapper.Map<SimpleDestination>(new SimpleSource { Id = 1, Name = "Ada" });
// result.Id == 1
// result.Name == "Ada"
2. Custom member mapping with ForMember
Use ForMember to compute or transform a single top-level property.
var config = new MapperConfig();
config.CreateMap<SimpleSource, SimpleDestination>()
.ForMember(dest => dest.Name, src => src.Name.ToUpperInvariant());
IMapper mapper = new Mapper(config);
var result = mapper.Map<SimpleDestination>(new SimpleSource { Id = 1, Name = "Ada" });
// result.Name == "ADA"
3. Nested object mapping
When a destination property's type differs from the source property it
corresponds to, ForMember's function must produce the
already-mapped value itself — it does not happen implicitly. The usual
pattern is to close over a Mapper built from the same
config and call back into it:
public class Country { public string Name { get; set; } = ""; }
public class CountryViewModel { public string Name { get; set; } = ""; }
public class Organization
{
public string OrgName { get; set; } = "";
public Country Country { get; set; } = new();
}
public class OrganizationViewModel
{
public string OrgName { get; set; } = "";
public CountryViewModel CountryViewModel { get; set; } = new();
}
var config = new MapperConfig();
config.CreateMap<Country, CountryViewModel>();
var mapper = new Mapper(config);
config.CreateMap<Organization, OrganizationViewModel>()
.ForMember(dest => dest.CountryViewModel,
src => mapper.Map<CountryViewModel>(src.Country));
var result = mapper.Map<OrganizationViewModel>(new Organization
{
OrgName = "Acme",
Country = new Country { Name = "Wonderland" }
});
// result.OrgName == "Acme"
// result.CountryViewModel.Name == "Wonderland"
src.Country
straight through (without the mapper.Map<CountryViewModel>(...)
call) throws InvalidOperationException at runtime, since a
Country instance cannot be assigned to a
CountryViewModel property. This exact mistake was previously
in this project's own README — it's called out here so it doesn't happen
to you.
4. Deep nested paths with ForPath
ForPath targets a property several levels deep. Multiple
ForPath calls under the same top-level destination property
are all applied to the same nested instance.
public class Location
{
public string Address { get; set; } = "";
public Organization Organization { get; set; } = new();
}
public class LocationViewModel
{
public string Address { get; set; } = "";
public OrganizationViewModel OrganizationViewModel { get; set; } = new();
}
var config = new MapperConfig();
config.CreateMap<Location, LocationViewModel>()
.ForPath(dest => dest.OrganizationViewModel.CountryViewModel.Name,
src => src.Organization.Country.Name)
.ForPath(dest => dest.OrganizationViewModel.OrgName,
src => src.Organization.OrgName);
var mapper = new Mapper(config);
var result = mapper.Map<LocationViewModel>(new Location
{
Address = "1 Main St",
Organization = new Organization
{
OrgName = "Acme",
Country = new Country { Name = "Wonderland" }
}
});
// result.Address == "1 Main St"
// result.OrganizationViewModel.OrgName == "Acme"
// result.OrganizationViewModel.CountryViewModel.Name == "Wonderland"
5. Collection mapping
Map a List<TSource> directly to a List<TDestination> — each element is mapped individually.
var config = new MapperConfig();
config.CreateMap<SimpleSource, SimpleDestination>();
IMapper mapper = new Mapper(config);
var sources = new List<SimpleSource>
{
new() { Id = 1, Name = "Ada" },
new() { Id = 2, Name = "Alan" },
};
var result = mapper.Map<List<SimpleDestination>>(sources);
// result.Count == 2
// result[0].Name == "Ada"
// result[1].Name == "Alan"
6. Nested collection properties
A List<T> destination property (not just the
top-level Map<List<T>> call) is also auto-mapped, as
long as a map is registered for the item types.
public class Employee { public string Name { get; set; } = ""; }
public class EmployeeViewModel { public string Name { get; set; } = ""; }
public class Department
{
public string DeptName { get; set; } = "";
public List<Employee> Employees { get; set; } = new();
}
public class DepartmentViewModel
{
public string DeptName { get; set; } = "";
public List<EmployeeViewModel> Employees { get; set; } = new();
}
var config = new MapperConfig();
config.CreateMap<Employee, EmployeeViewModel>();
config.CreateMap<Department, DepartmentViewModel>();
IMapper mapper = new Mapper(config);
var result = mapper.Map<DepartmentViewModel>(new Department
{
DeptName = "Engineering",
Employees = new List<Employee>
{
new() { Name = "Ada" },
new() { Name = "Alan" },
}
});
// result.DeptName == "Engineering"
// result.Employees.Count == 2
// result.Employees[0].Name == "Ada"
EmployeeViewModel[] Employees instead of
List<EmployeeViewModel> Employees on
DepartmentViewModel maps the same way — the source property still
needs to be a List<T>, but the destination property can be a
List<T>, any of IList<T>/ICollection<T>/IReadOnlyList<T>/IReadOnlyCollection<T>/IEnumerable<T>, or an array.