laget.Mapper
1.3.27
Prefix Reserved
dotnet add package laget.Mapper --version 1.3.27
NuGet\Install-Package laget.Mapper -Version 1.3.27
<PackageReference Include="laget.Mapper" Version="1.3.27" />
paket add laget.Mapper --version 1.3.27
#r "nuget: laget.Mapper, 1.3.27"
// Install laget.Mapper as a Cake Addin #addin nuget:?package=laget.Mapper&version=1.3.27 // Install laget.Mapper as a Cake Tool #tool nuget:?package=laget.Mapper&version=1.3.27
laget.Mapper
An extremely simple object-object mapper.
Configuration
This example is shown using Autofac since this is the go-to IoC for us.
await Host.CreateDefaultBuilder()
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.RegisterMappers();
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.Build()
.RunAsync();
This is the simplest way to register your mappers but also has some constraints:
- The mapper implementations must exist in the program that calls
RegisterMappers
. - The mapper implementations must implement the interface
IMapper
.
await Host.CreateDefaultBuilder()
.ConfigureContainer<ContainerBuilder>((context, builder) =>
{
builder.RegisterMappers(_ =>
{
_.TheCallingAssembly();
_.TheCallingAssembly<T>();
_.AssemblyContainingType<T>();
_.Assembly("Mappers");
});
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.Build()
.RunAsync();
This is the advanced and more customizable way to register your mappers
TheCallingAssembly();
will register mapper implementations from the calling assembly that implements the interfaceIMapper
.TheCallingAssembly<T>();
will register mapper implementations from the calling assembly that implements the interfaceT
.AssemblyContainingType<T>();
will register mapper implementations from the assembly of the provided type, this is useful if you e.g. have class libraries with Mappers and/or custom implementations ofIMapper
.Assembly("name");
will register mapper implementations in the assembly, will load assembly via the name provided usingSystem.Reflection
, that implements the interfaceIMapper
.
Usage
Creating a mapper class
To create a mapper class use the marker interface IMapper
to mark the class and the MapperMethod
attribute to mark all methods in the class that are mapping methods.
The global mapper will pick up all classes tagged with the IMapper
marker interface and register all methods tagged with the MapperMethod
that match the following critera
- The method is not private
- The method has a non void return value
- The method has only one parameter
public class ModelMapper : IMapper
{
[MapperMethod] // Will be registered as the mapping method for converting Model -> Entity
public Entity ModelToEntity(Model model) =>
new Entity
{
// ...
};
[MapperMethod] // Will be registered as the mapping method for converting Dto -> Model
public Model ModelFromDto(Dto dto) =>
new Model
{
// ...
};
[MapperMethod] // Will not be registered as the mapping method for converting Dto -> Model is already defined above
public Model ModelFromDto2(Dto dto) =>
new Model
{
// ...
};
// Will not be registered as it lacks the MapperMethod attribute
public Dto DtoFromModel(Model model) =>
new Dto
{
// ...
};
[MapperMethod] // Will not be registered as it is a private method
private Model ModelFromEntity(Entity entity) =>
new Model
{
// ...
};
[MapperMethod] // Will not be registered as it returns void
public void UpdateModelState(Model model) { /* ... */ }
[MapperMethod] // Will not be registered as it doesn't take a parameter
public int GetConstantInt() => 42;
[MapperMethod] // Will not be registered as it takes multiple arguments
public Model ModelFromEntityAndDto(Entity entity, Dto dto) =>
new Model
{
// ...
};
}
Using the mapper
The mapper can be used in different ways, either through direct access to the static method
var model = new Model();
var dto = Mapper.Mapper.Map<Dto>(model);
var baseClassDto = Mapper.Mapper.Map<ModelBase, DtoBase>(model);
Or using one of the built in extensions on object
or IEnumerable<TSource>
var model = new Model();
var dto = model.Map<Dto>();
var dtos = new [] { new Dto() /*, ... */ };
var models = dtos.Map<Model>();
Using the extensions is the recommended way as it provides a clean way of writing Linq chains, however it can be useful to access the mapper directly if you need to map based on an inherited class.
Benchmarks
BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4123/22H2/2022Update) (VMware)
AMD Ryzen Threadripper 3960X, 1 CPU, 12 logical and 12 physical cores
.NET SDK 8.0.200
[Host] : .NET 6.0.27 (6.0.2724.6912), X64 RyuJIT AVX2
Job-BJZLVN : .NET 6.0.27 (6.0.2724.6912), X64 RyuJIT AVX2
Job-OQIHXW : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
IterationCount=10 LaunchCount=1 RunStrategy=Throughput WarmupCount=5
Mappings
Method | Runtime | Mean | Error | StdDev | Min | Max | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Simple_Mapper | .NET 6.0 | 169.49 ns | 3.408 ns | 2.254 ns | 166.39 ns | 172.78 ns | 168.89 ns | 1.00 | 0.00 | 0.0172 | 144 B | 1.00 |
Simple_Mapper | .NET 8.0 | 63.00 ns | 4.291 ns | 2.838 ns | 59.19 ns | 67.89 ns | 62.52 ns | 0.37 | 0.02 | 0.0172 | 144 B | 1.00 |
DeepType_Mapper | .NET 6.0 | 976.40 ns | 9.541 ns | 5.678 ns | 971.22 ns | 986.86 ns | 975.08 ns | 1.00 | 0.00 | 0.1411 | 1184 B | 1.00 |
DeepType_Mapper | .NET 8.0 | 461.82 ns | 27.469 ns | 18.169 ns | 433.24 ns | 488.14 ns | 466.44 ns | 0.48 | 0.02 | 0.1411 | 1184 B | 1.00 |
Registration
Method | Mean | Error | StdDev | Min | Max | Median | Gen0 | Allocated |
---|---|---|---|---|---|---|---|---|
Single_Registration | 47.44 ns | 5.158 ns | 15.127 ns | 46.44 ns | 21.13 ns | 1,989.74 ns | 0.0839 | 720 B |
Multiple_Registration | 72.98 ns | 13.068 ns | 38.532 ns | 75.02 ns | 85.02 ns | 4,160.33 ns | 0.1831 | 1568 B |
Assembly_Registration | 52.25 ns | 2.468 ns | 7.160 ns | 52.30 ns | 36.57 ns | 1,076.43 ns | 0.0515 | 432 B |
AssemblyContainingType_Registration | 47.87 ns | 1.102 ns | 3.248 ns | 47.74 ns | 43.13 ns | 53.77 ns | 0.0334 | 280 B |
TheCallingAssembly_Registration | 54.38 ns | 0.764 ns | 2.254 ns | 53.33 ns | 50.01 ns | 57.88 ns | 0.0334 | 280 B |
TheCallingAssemblyT_Registration | 54.31 ns | 1.045 ns | 3.082 ns | 54.44 ns | 48.48 ns | 59.92 ns | 0.0334 | 280 B |
TheEntryAssembly_Registration | 50.83 ns | 1.015 ns | 2.993 ns | 49.76 ns | 47.22 ns | 59.54 ns | 0.0334 | 280 B |
TheEntryAssemblyT_Registration | 49.96 ns | 0.665 ns | 1.961 ns | 48.95 ns | 47.30 ns | 52.91 ns | 0.0334 | 280 B |
TheExecutingAssembly_Registration | 657.93 ns | 1.320 ns | 3.831 ns | 657.71 ns | 649.10 ns | 667.97 ns | 0.0334 | 280 B |
TheExecutingAssemblyT_Registration | 699.09 ns | 2.773 ns | 8.089 ns | 699.08 ns | 684.46 ns | 717.44 ns | 0.0334 | 280 B |
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
- Microsoft.Bcl.HashCode (>= 1.1.1)
-
.NETStandard 2.1
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
-
net6.0
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
-
net8.0
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.