File: README.md
Mapster - The Mapper of Your Domain
Writing mapping methods is a machine job. Do not waste your time, let Mapster do it.
NuGet Sources
NuGet Packages
| Package | Stable | Pre-release |
|---|---|---|
| Mapster | ||
| Mapster.Core | ||
| Mapster.DependencyInjection | ||
| Mapster.EFCore | ||
| Mapster.EF6 | ||
| Mapster.JsonNet | ||
| Mapster.Immutable | ||
| Mapster.Diagnostics | ||
| ExpressionDebugger |
DotNet Tools
| Tool | Stable | Pre-release |
|---|---|---|
| Mapster.Tool |
Installation
Install Mapster with the NuGet CLI:
Install-Package MapsterOr use the .NET core CLI to install Mapster:
dotnet add package Mapster --projectBasic usage
Mapping to a new object
Mapster creates the destination object and maps values to it.
var destObject = sourceObject.Adapt<Destination>();Mapping to an existing object
You create the object, Mapster maps to the object.
sourceObject.Adapt(destObject);Use Mapster with Dependency Injection
You can get your IMapper instance via dependency injection, so you do not have to change code, when migrating to mapster from automapper!
Just add Mapster to service collection:
services.AddMapster();And use it with DI in your Project:
public class Test
{
public Test(IMapper mapper)
{
var sourceObject = mapper.Adapt<Destination>();
}
}Queryable Extensions
Mapster also provides extensions to map queryables.
using (MyDbContext context = new MyDbContext())
{
// Build a Select Expression from DTO
var destinations = context.Sources.ProjectToType<Destination>().ToList();
// Versus creating by hand:
var destinations = context.Sources.Select(c => new Destination {
Id = c.Id,
Name = c.Name,
Surname = c.Surname,
....
})
.ToList();
}Generating models & mappers
No need to write your own DTO classes. Mapster provides Mapster.Tool to help you generating models. And if you would like to have explicit mapping, Mapster also generates mapper class for you.
[AdaptTo("[name]Dto"), GenerateMapper]
public class Student {
...
}Then Mapster will generate for you:
public class StudentDto {
...
}
public static class StudentMapper {
public static StudentDto AdaptToDto(this Student poco) { ... }
public static StudentDto AdaptTo(this Student poco, StudentDto dto) { ... }
public static Expression<Func<Student, StudentDto>> ProjectToDto => ...
}What's new
- Fluent API for code generation
- Automatically generate mapping code on build
- Define setting to nested mapping
ISet,IDictionary,IReadOnlyDictionarysupportEmptyCollectionIfNull,CreateNewIfNullDestinationTransform- Several fixes
- New plugins
Why Mapster?
Performance & Memory efficient
Mapster was designed to be efficient on both speed and memory. The repository includes a benchmark project in src/Benchmark that compares the local Mapster build, its compiler variants, and other modern mapping libraries like AutoMapper, Mapperly, and Facet.
- Roslyn Compiler
- FEC
- Code generation
- Facet
- Mapperly
The snapshot below shows the FlatTypes scenario (Person -> PersonDTO), a best-case DTO with simple property-to-property mapping and no nested objects or collections.
[!NOTE]
More complex object shapes can change the relative results. See the complete benchmark results forComplexTypes,RecursiveTypes, andTotalAllTypes.
| Method | MapOperations | Mean | StdDev | Error | Ns/Map | Ratio | Gen0 | Allocated | Alloc Ratio | Bytes/Map |
|---|---|---|---|---|---|---|---|---|---|---|
Mapster 10.0.8 |
1000000 | 6.849 ms | 0.6851 ms | 1.0358 ms | 6.849 | 1.01 | 4781 | 76.29 MB | 1.00 | 80 |
Mapster 10.0.8 (Roslyn) |
1000000 | 6.579 ms | 0.2782 ms | 0.4206 ms | 6.579 | 0.97 | 4781 | 76.29 MB | 1.00 | 80 |
Mapster 10.0.8 (FEC) |
1000000 | 6.549 ms | 0.9130 ms | 1.3803 ms | 6.549 | 0.97 | 4781 | 76.29 MB | 1.00 | 80 |
Mapster 10.0.8 (Codegen) |
1000000 | 5.868 ms | 0.3266 ms | 0.5488 ms | 5.868 | 0.86 | 4781 | 76.29 MB | 1.00 | 80 |
AutoMapper 14.0.0 |
1000000 | 29.645 ms | 0.8963 ms | 1.5062 ms | 29.645 | 4.37 | 4750 | 76.29 MB | 1.00 | 80 |
Facet 6.5.5 |
1000000 | 7.801 ms | 1.0231 ms | 1.5467 ms | 7.801 | 1.15 | 8601 | 137.33 MB | 1.80 | 144 |
Facet 6.5.5 (Compiled Projection) |
1000000 | 5.508 ms | 0.7064 ms | 1.0679 ms | 5.508 | 0.81 | 4781 | 76.29 MB | 1.00 | 80 |
Mapperly 4.3.1 |
1000000 | 6.521 ms | 0.8369 ms | 1.2652 ms | 6.521 | 0.96 | 4781 | 76.29 MB | 1.00 | 80 |
Step into debugging
Step-into debugging lets you debug your mapping and inspect values just like your code.
Code Generation
Code generation allows you to
- Validate mapping at compile time
- Getting raw performance
- Seeing your mapping code & debugging
- Finding usage of your models' properties
There are currently two tools which you can choose based on your preferences.
- Mapster.Tool NEW!
- TextTemplate
Change logs
https://github.com/MapsterMapper/Mapster/releases
Usage Guides with Translations
- English
- ไธญๆๆๆกฃ (sp thx to @staneee)
Acknowledgements
JetBrains kindly provides Mapster with a free open-source licence for their Resharper and Rider.
- Resharper makes Visual Studio a much better IDE
- Rider is fast & powerful cross platform .NET IDE
File: docs/api/index.md
MapsterMapper Mapster API Documentation
Welcome in the Mapster API documentation!
Use the table of contents to browse API documentation for the MapsterMapper.Mapster Package.
File: docs/api/Reference.md
uid: Mapster.References
References
Basic
| Method | Description | Link |
|---|---|---|
src.Adapt<Dest>() |
Mapping to new type | basic |
src.Adapt(dest) |
Mapping to existing object | basic |
query.ProjectToType<Dest>() |
Mapping from queryable | basic |
| Convention & Data type support | data types |
Mapper instance (for dependency injection)
| Method | Description | Link |
|---|---|---|
IMapper mapper = new Mapper() |
Create mapper instance | mappers |
mapper.Map<Dest>(src) |
Mapping to new type | |
mapper.Map(src, dest) |
Mapping to existing object |
Builder (for complex mapping)
| Method | Description | Link |
|---|---|---|
src.BuildAdapter() mapper.From(src) |
Create builder | mappers |
.ForkConfig(config => ...) |
Inline configuration | config location |
.AddParameters(name, value) |
Passing runtime value | setting values |
.AdaptToType<Dest>() |
Mapping to new type | |
.AdaptTo(dest) |
Mapping to existing object | |
.CreateMapExpression<Dest>() |
Get mapping expression | |
.CreateMapToTargetExpression<Dest>() |
Get mapping to existing object expression | |
.CreateProjectionExpression<Dest>() |
Get mapping from queryable expression |
Config
| Method | Description | Link |
|---|---|---|
TypeAdapterConfig.GlobalSettings |
Global config | config |
var config = new TypeAdapterConfig() |
Create new config instance | config instance |
src.Adapt<Dest>(config) |
Passing config to mapping | |
new Mapper(config) |
Passing config to mapper instance | |
src.BuildAdapter(config) |
Passing config to builder | |
config.RequireDestinationMemberSource |
Validate all properties are mapped | config validation |
config.RequireExplicitMapping |
Validate all type pairs are defined | config validation |
config.AllowImplicitDestinationInheritance |
Use config from destination based class | inheritance |
config.AllowImplicitSourceInheritance |
Use config from source based class | inheritance |
config.SelfContainedCodeGeneration |
Generate all nested mapping in 1 method | TextTemplate |
config.Compile() |
Validate mapping instruction & cache | config validation |
config.CompileProjection() |
Validate mapping instruction & cache for queryable | |
config.Clone() |
Copy config | config instance |
config.Fork(forked => ...) |
Inline configuration | config location |
Config scanning
| Method | Description | Link |
|---|---|---|
IRegister |
Interface for config scanning | config location |
config.Scan(...assemblies) |
Scan for config in assemblies | config location |
config.Apply(...registers) |
Apply registers directly | config location |
Declare settings
| Method | Description | Link |
|---|---|---|
config.Default |
Get setting applied to all type pairs | config |
TypeAdapterConfig<Src, Dest>.NewConfig() config.NewConfig<Src, Dest>() |
Create setting applied to specific type pairs | config |
TypeAdapterConfig<Src, Dest>.ForType() config.ForType<Src, Dest>() |
Get setting applied to specific type pairs | config |
config.ForType(typeof(GenericPoco<>),typeof(GenericDto<>)) |
Get setting applied to generic type pairs | config |
config.When((src, dest, mapType) => ...) |
Get setting that applied conditionally | config |
config.ForDestinationType<Dest>() |
Get setting that applied to specific destination type | config |
| Configuration for nested mapping | nested mapping |
Settings
| Method | Description | Apply to queryable | Link |
|---|---|---|---|
AddDestinationTransform |
Clean up data for a specific type | x | setting values |
AfterMapping |
Add steps after mapping done | before-after | |
AvoidInlineMapping |
Skip inline process for large type mapping | object reference | |
BeforeMapping |
Add steps before mapping start | before-after | |
ConstructUsing |
Define how to create object | x | constructor |
EnableNonPublicMembers |
Mapping non-public properties | non-public | |
EnumMappingStrategy |
Choose whether mapping enum by value or by name | data types | |
Fork |
Add new settings without side effect on main config | x | nested mapping |
GetMemberName |
Define how to resolve property name | x | custom naming |
Ignore |
Ignore specific properties | x | ignore |
IgnoreAttribute |
Ignore specific attributes annotated on properties | x | attribute |
IgnoreIf |
Ignore conditionally | x | ignore |
IgnoreMember |
Setup rules to ignore | x | rule based |
IgnoreNonMapped |
Ignore all properties not defined in Map |
x | ignore |
IgnoreNullValues |
Not map if src property is null | shallow & merge | |
Include |
Include derived types on mapping | inheritance | |
IncludeAttribute |
Include specific attributes annotated on properties | x | attribute |
IncludeMember |
Setup rules to include | x | rule based |
Inherits |
Copy setting from based type | x | inheritance |
Map |
Define property pairs | x | custom mapping |
MapToConstructor |
Mapping to constructor | x | constructor |
MapToTargetWith |
Define how to map to existing object between type pair | custom conversion | |
MapWith |
Define how to map between type pair | x | custom conversion |
MaxDepth |
Limit depth of nested mapping | x | object reference |
NameMatchingStrategy |
Define how to resolve property's name | x | custom naming |
PreserveReference |
Tracking reference when mapping | object reference | |
ShallowCopyForSameType |
Direct assign rather than deep clone if type pairs are the same | shallow & merge | |
TwoWays |
Define type mapping are 2 ways | x | 2-ways & unflattening |
Unflattening |
Allow unflatten mapping | x | 2-ways & unflattening |
UseDestinationValue |
Use existing property object to map data | readonly-prop |
Attributes
| Annotation | Description | Link |
|---|---|---|
[AdaptMember(name)] |
Mapping property to different name | attribute |
[AdaptIgnore(side)] |
Ignore property from mapping | attribute |
[UseDestinationValue] |
Use existing property object to map data | attribute |
[AdaptTo] [AdaptFrom] [AdaptTwoWays] |
Add setting on POCO class | location |
[Mapper] [GenerateMapper] [PropertyType] |
Define setting for code generation | Mapster.Tool |
Packages
| Packages | Method | Description |
|---|---|---|
| Async | setting.AfterMappingAsync builder.AdaptToTypeAsync |
perform async operation on mapping |
| Debugging | config.Compiler = exp => exp.CompileWithDebugInfo() |
compile to allow step into debugging |
| Dependency Injection | MapContext.Current.GetService() |
Inject service into mapping logic |
| EF 6 & EF Core | builder.EntityFromContext |
Copy data to tracked EF entity |
| FEC | config.Compiler = exp => exp.CompileFast() |
compile using FastExpressionCompiler |
| Immutable | config.EnableImmutableMapping() |
mapping to immutable collection |
| Json.net | config.EnableJsonMapping() |
map json from/to poco and string |
Code Generation Tools
| Plugin | Tool | Description |
|---|---|---|
| Mapster.Tool | dotnet mapster |
generate DTOs and mapping codes on build |
| TextTemplate | t4 |
generate mapping codes using t4 |
File: docs/articles/configuration/Config-for-nested-mapping.md
uid: Mapster.Configuration.NestedMapping title: "Configuration - Config for nested mapping"
For example if you have parent and child classes.
class ParentPoco
{
public string Id { get; set; }
public List<ChildPoco> Children { get; set; }
public string Name { get; set; }
}
class ChildPoco
{
public string Id { get; set; }
public List<GrandChildPoco> GrandChildren { get; set; }
}
class GrandChildPoco
{
public string Id { get; set; }
}And if you have setting on parent type.
TypeAdapterConfig.NewConfig()
.PreserveReference(true);By default, children types will not get effect from PreserveReference.
To do so, you must specify all type pairs inside ParentPoco.
TypeAdapterConfig.NewConfig()
.PreserveReference(true);
TypeAdapterConfig<ChildPoco, ChildDto>.NewConfig()
.PreserveReference(true);
TypeAdapterConfig<GrandChildPoco, GrandChildDto>.NewConfig()
.PreserveReference(true);Or you can set PreserveReference in global setting.
TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);Fork
You can use Fork command to define config that applies only specified mapping down to nested mapping without polluting global setting.
TypeAdapterConfig.NewConfig()
.Fork(config => config.Default.PreserveReference(true));Ignore if string is null or empty
Another example, Mapster only can ignore null value (IgnoreNullValues), however, you use Fork to ignore null or empty.
TypeAdapterConfig.NewConfig()
.Fork(config => config.ForType<string, string>()
.MapToTargetWith((src, dest) => string.IsNullOrEmpty(src) ? dest : src)
);File: docs/articles/configuration/Config-inheritance.md
uid: Mapster.Configuration.Inheritance title: "Configuration - Inheritance"
Implicit inheritance
Type mappings will automatically inherit for source types. Ie. if you set up following config.
TypeAdapterConfig<SimplePoco, SimpleDto>.NewConfig()
.Map(dest => dest.Name, src => src.Name + "_Suffix");A derived type of SimplePoco will automatically apply the base mapping config.
var dest = TypeAdapter.Adapt<DerivedPoco, SimpleDto>(src);
//dest.Name = src.Name + "_Suffix"If you don't wish for a derived type to use the base mapping, you can turn it off by using AllowImplicitSourceInheritance
TypeAdapterConfig.GlobalSettings.AllowImplicitSourceInheritance = false;And by default, Mapster will not inherit destination type mappings. You can turn it on by AllowImplicitDestinationInheritance.
TypeAdapterConfig.GlobalSettings.AllowImplicitDestinationInheritance = true;Explicit inheritance
You can copy setting from based type explicitly.
TypeAdapterConfig<DerivedPoco, DerivedDto>.NewConfig()
.Inherits<SimplePoco, SimpleDto>();Include derived types
You can also include derived type to the based type declaration. For example:
TypeAdapterConfig<Vehicle, VehicleDto>.NewConfig()
.Include<Car, CarDto>();
Vehicle vehicle = new Car { Id = 1, Name = "Car", Make = "Toyota" };
var dto = vehicle.Adapt<Vehicle, VehicleDto>();
dto.ShouldBeOfType<CarDto>();
((CarDto)dto).Make.ShouldBe("Toyota"); //The 'Make' property doesn't exist in VehicleFile: docs/articles/configuration/Config-instance.md
uid: Mapster.Configuration.Instance title: "Configuration - Config Instance"
Creating `Config` Instance with `TypeAdapterConfig`
You may wish to have different settings in different scenarios.
If you would not like to apply setting at a static level, Mapster also provides setting instance configurations.
var config = new TypeAdapterConfig();
config.Default.Ignore("Id");`ForType` Configuration Methods
For instance configurations, you can use the same NewConfig and ForType methods that are used at the global level with
the same behavior: NewConfig drops any existing configuration and ForType creates or enhances a configuration.
config.NewConfig<TSource, TDestination>()
.Map(dest => dest.FullName,
src => string.Format("{0} {1}", src.FirstName, src.LastName));
config.ForType<TSource, TDestination>()
.Map(dest => dest.FullName,
src => string.Format("{0} {1}", src.FirstName, src.LastName));`Adapt` Configuration Methods
You can apply a specific config instance by passing it to the Adapt method. (NOTE: please reuse your config instance to prevent recompilation)
var result = src.Adapt(config);`Map` Configuration Methods
Or to a Mapper instance.
var mapper = new Mapper(config);
var result = mapper.Map(src);Cloning `Config` Instance
If you would like to create configuration instance from existing configuration, you can use Clone method. For example, if you would like to clone from global setting.
var newConfig = TypeAdapterConfig.GlobalSettings.Clone();Or clone from existing configuration instance
var newConfig = oldConfig.Clone();`Fork` Configuration
Fork is similar to Clone, but Fork will allow you to keep configuration and mapping in the same location. See Config Location for more info.
var forked = mainConfig.Fork(config =>
config.ForType()
.Map(dest => dest.code, src => src.Id));
var dto = poco.Adapt<Dto>(forked);File: docs/articles/configuration/Config-location.md
uid: Mapster.Configuration.Location title: "Configuration - Location"
Entry point for configuration
Configuration should be set only once and reuse for mapping. Therefore, we should not keep configuration and mapping in the same location. For example:
config.ForType().Ignore("Id");
var dto1 = poco1.Adapt<Dto>(config);
config.ForType().Ignore("Id"); //<--- Exception occurred here, because config was already compiled
var dto2 = poco2.Adapt<Dto>(config);Therefore, you should separate configuration and mapping. Configuration should keep in entry point such as Main function or Global.asax.cs or Program.cs / Startup.cs.
// Application_Start in Global.asax.cs
config.ForType().Ignore("Id");// in Controller class
var dto1 = poco1.Adapt<Dto>(config);
var dto2 = poco2.Adapt<Dto>(config);Keep together with mapping
A potential problem with separating configuration and mapping is that the code will be separated into 2 locations. You might remove or alter mapping, and you can forget to update the configuration. Fork method allow you to keep config and mapping inline.
var dto = poco.Adapt<Dto>(config.Fork(forked => forked.ForType().Ignore("Id"));Don't worry about performance, forked config will be compiled only once. When mapping occurs for the second time, Fork function will return config from cache.
Using Fork in generic class or method
Fork method uses filename and line number and the key. But if you use Fork method inside generic class or method, you must specify your own key (with all type names) to prevent Fork to return invalid config from different type arguments.
IQueryable GetItems<TPoco, TDto>()
{
var forked = config.Fork(
f => f.ForType<TPoco, TDto>().Ignore("Id"),
$"MyKey|{typeof(TPoco).FullName}|{typeof(TDto).FullName}");
return db.Set<TPoco>().ProjectToType(forked);
}In separated assemblies
It's relatively common to have mapping configurations spread across a number of different assemblies.
Perhaps your domain assembly has some rules to map to domain objects and your web api has some specific rules to map to your api contracts.
Scan method
It can be helpful to allow assemblies to be scanned for these rules so you have some basic method of organizing your rules and not forgetting to have the registration code called. In some cases, it may even be necessary to register the assemblies in a particular order, so that some rules override others. Assembly scanning helps with this.
Assembly scanning is simple, just create any number of IRegister implementations in your assembly, then call Scan from your TypeAdapterConfig class:
public class MyRegister : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<TSource, TDestination>();
//OR to create or enhance an existing configuration
config.ForType<TSource, TDestination>();
}
}To scan and register at the Global level:
TypeAdapterConfig.GlobalSettings.Scan(assembly1, assembly2, assemblyN)For a specific config instance:
var config = new TypeAdapterConfig();
config.Scan(assembly1, assembly2, assemblyN);Apply method
If you use other assembly scanning library such as MEF, you can easily apply registration with Apply method.
var registers = container.GetExports();
config.Apply(registers);Apply method also allows you to selectively pick from one or more IRegister rather than every IRegister in assembly.
var register = new MockingRegister();
config.Apply(register);Attributes
You can also set config together with your POCO classes. For example:
[AdaptTo(typeof(StudentDto), PreserveReference = true)]
public class Student {
...
}File: docs/articles/configuration/Config-validation-and-compilation.md
uid: Mapster.Configuration.ValidationAndCompilation title: "Configuration - Validation and Compilation"
To validate your mapping in unit tests and in order to help with "Fail Fast" situations, the following strict mapping modes have been added.
Explicit Mapping
Forcing all classes to be explicitly mapped:
//Default is "false"
TypeAdapterConfig.GlobalSettings.RequireExplicitMapping = true;
//This means you have to have an explicit configuration for each class, even if it's just:
TypeAdapterConfig.NewConfig();Checking Destination Member
Forcing all destination properties to have a corresponding source member or explicit mapping/ignore:
//Default is "false"
TypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource = true;Validating Mappings
Both a specific TypeAdapterConfig or all current configurations can be validated. In addition, if Explicit Mappings (above) are enabled, it will also include errors for classes that are not registered at all with the mapper.
//Validate a specific config
var config = TypeAdapterConfig.NewConfig();
config.Compile();
//Validate globally
TypeAdapterConfig.NewConfig();
TypeAdapterConfig.NewConfig();
TypeAdapterConfig.GlobalSettings.Compile();Config Compilation
Mapster will automatically compile mapping for first time usage.
var result = poco.Adapt<Dto>();However, you can explicitly compile mapping by Compile method.
//Global config
TypeAdapterConfig.GlobalSettings.Compile();
//Config instance
var config = new TypeAdapterConfig();
config.Compile();Calling Compile method on start up helps you validate mapping and detect problem on start-up time, not on run-time.
NOTE: After compile, when you change setting in config, it will generate errors. Therefore, make sure you finish configuration before calling Compile.
File: docs/articles/configuration/Configuration.md
uid: Mapster.Configuration.Overview title: "Configuration - Overview"
Setting per type pair
You can easily create settings for a type mapping by using: TypeAdapterConfig<TSource, TDestination>.NewConfig().
When NewConfig is called, any previous configuration for this particular TSource => TDestination mapping is dropped.
TypeAdapterConfig<TSource, TDestination>
.NewConfig()
.Ignore(dest => dest.Age)
.Map(dest => dest.FullName,
src => string.Format("{0} {1}", src.FirstName, src.LastName));As an alternative to NewConfig, you can use ForType in the same way:
TypeAdapterConfig<TSource, TDestination>
.ForType()
.Ignore(dest => dest.Age)
.Map(dest => dest.FullName,
src => string.Format("{0} {1}", src.FirstName, src.LastName));ForType differs in that it will create a new mapping if one doesn't exist, but if the specified TSource => TDestination
mapping does already exist, it will enhance the existing mapping instead of dropping and replacing it.
Global setting
Use global settings to apply policies to all mappings.
TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);Then for individual type mappings, you can easily override the global setting(s).
TypeAdapterConfig<SimplePoco, SimpleDto>.NewConfig().PreserveReference(false);Rule based settings
To set the setting at a more granular level. You can use the When method in global settings.
In the example below, when any source type and destination type are the same, we will not the copy the Id property.
TypeAdapterConfig.GlobalSettings.When((srcType, destType, mapType) => srcType == destType)
.Ignore("Id");In this example, the config would only apply to Query Expressions (projections).
TypeAdapterConfig.GlobalSettings.When((srcType, destType, mapType) => mapType == MapType.Projection)
.IgnoreAttribute(typeof(NotMapAttribute));Destination type only
A setting can also be created without knowing the source type, by using ForDestinationType. For example, you can do AfterMapping setting to validate after mapping.
TypeAdapterConfig.GlobalSettings.ForDestinationType()
.AfterMapping(dest => dest.Validate());[!NOTE]
ForDestinationTypeabove will always apply to all types assignable toIValidator. If destination class implementsIValidator, it will also apply theAfterMappingconfig.
Open generics
If the mapping type is generic, you can create a setting by passing generic type definition to ForType.
TypeAdapterConfig.GlobalSettings.ForType(typeof(GenericPoco<>), typeof(GenericDto<>))
.Map("value", "Value");[!Note]
Starting with Mapster version 10.0.8, validation for type pairs settings containing open generic type is disabled.
If you require validation of such settings, you must register the configuration for at least one pair of closed generic types:csharpTypeAdapterConfig.GlobalSettings.RequireDestinationMemberSource = true; // check all destination member mapping TypeAdapterConfig.GlobalSettings.ForType(typeof(GenericPoco<>), typeof(GenericDto<>)) .Map("value", "Value"); TypeAdapterConfig<GenericPoco, GenericDto<string>>.NewConfig(); TypeAdapterConfig.GlobalSettings.Compile(); // validate
File: docs/articles/mapping/data-types/Collections.md
uid: Mapster.Mapping.DataTypes.Collections title: "Mapping - Collections"
Collections
This includes mapping among lists, arrays, collections, dictionary including various interfaces: IList<T>, ICollection<T>, IEnumerable<T>, ISet<T>, IDictionary<TKey, TValue> etc...
var list = db.Pocos.ToList();
var target = list.Adapt>();