ObjectMap.NET 1.0.7

There is a newer version of this package available.
See the version list below for details.
dotnet add package ObjectMap.NET --version 1.0.7
                    
NuGet\Install-Package ObjectMap.NET -Version 1.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ObjectMap.NET" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ObjectMap.NET" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="ObjectMap.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ObjectMap.NET --version 1.0.7
                    
#r "nuget: ObjectMap.NET, 1.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ObjectMap.NET@1.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ObjectMap.NET&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=ObjectMap.NET&version=1.0.7
                    
Install as a Cake Tool

ObjectMap.NET

A lightweight, convention-based object mapper for modern .NET.

NuGet: ObjectMap.NET
Namespaces: SimpleMapper.*
Target framework: net10.0

ObjectMap.NET is designed for explicit maps — every (source → destination) pair is registered in a profile. Convention handles the common cases; fluent configuration covers the rest.


Installation

dotnet add package ObjectMap.NET

Local project reference:

<ProjectReference Include="path\to\SR.ObjectMapper.NET.csproj" />

Quick start

1. Register the mapper

using SimpleMapper.Mapper.DependencyInjection;
using SimpleMapper.Mapper.Profiles;

services.AddSRSimpleMapper(cfg =>
{
    cfg.RegisterProfile(new MyAppMappingProfile());
});

Optional global settings:

services.AddSRSimpleMapper(cfg =>
{
    cfg.DestinationMemberNaming = NamingConventions.SnakeCaseDestination;
    cfg.EnableAutoFlattening = true;
    cfg.RegisterProfile<MyAppMappingProfile>();
});

2. Define a profile

using SimpleMapper.Mapper.Profiles;

public class MyAppMappingProfile : Profile
{
    protected override void ConfigureMaps()
    {
        CreateMap<OrderDto, OrderEntity>()
            .ForMember(d => d.Total, o => o.MapFrom(s => s.Lines.Sum(l => l.Amount))
            .BeforeMap((dto, entity) => { /* runs before members are assigned */ })
            .AfterMap((dto, entity) => { /* runs after mapping completes */ })
            .ReverseMap();

        CreateMap<LineItemDto, LineItemEntity>();
    }
}

3. Inject and map

public class OrderService(ISRSimpleMapper mapper)
{
    public OrderEntity ToEntity(OrderDto dto) =>
        mapper.Map<OrderDto, OrderEntity>(dto);
}

Core API (ISRSimpleMapper)

Method Purpose
Map<TDestination>(object source) Map using the runtime type of source.
Map<TSource, TDestination>(TSource source) Map with compile-time source and destination types (preferred).
Map<TSource, TDestination>(TSource source, TDestination destination) Map into an existing instance (update / patch).
ProjectTo<TSource, TDestination>(IQueryable<TSource> query) Project a query using a cached expression tree (EF Core–friendly).

Nulls: Map<TSource, TDestination>(source) returns default when source is null.
Map(source, destination) throws ArgumentNullException if either argument is null.


Configuration

MapperConfiguration

Property Description
DestinationMemberNaming How destination member names relate to source names (default: PascalCase).
SourceMemberNaming Additional source-side naming convention for property lookup.
EnableAutoFlattening When true, nested source properties can populate flat destination members (default: true).

Built-in naming conventions (NamingConventions):

  • PascalCase — default, same names on both sides.
  • SnakeCaseDestination — source PascalCase → destination snake_case (e.g. UserName → user_name).
  • SnakeCaseSource — source snake_case → destination PascalCase.

Profile

Override ConfigureMaps() and call CreateMap<TSource, TDestination>() for every pair you map.


Fluent mapping API

CreateMap<TSource, TDestination>()

Registers a one-way map. Matching is by convention (name + compatible types), plus flattening and naming rules below.

ReverseMap()

Registers the inverse map TDestination → TSource and returns a TypeMapExpression<TDestination, TSource> so chained ForMember / hooks configure the reverse direction.

  • Ignored members are mirrored on the reverse map (a later ForMember(...).MapFrom(...) on the reverse expression clears that ignore).
  • Flattened members are reversed into nested paths (e.g. City → Address.City).
  • BeforeMap / AfterMap hooks are copied with swapped (source, destination) arguments so forward hooks run on the correct instances during reverse mapping.
  • Name-matched members with incompatible types (e.g. DbUserRole → string) are not auto-wired on reverse; use explicit ForMember (e.g. src.Role.Name).
  • Nested complex members (e.g. DbTopic → TopicNameResponse) are not cast by convention; they are mapped at runtime through the registered nested CreateMap / ReverseMap.

ForMember(dest => dest.Member, opt => { ... })

Call Effect
opt.Ignore() Skip this destination member.
opt.MapFrom(src => ...) Set the member from a custom expression.

BeforeMap / AfterMap

CreateMap<Entity, Dto>()
    .BeforeMap((src, dest) => { /* destination exists; members not yet assigned */ })
    .AfterMap((src, dest) => { /* all mapping complete */ });

On create-new maps, BeforeMap runs after an empty destination is created and before any members are assigned.

DisableAutoFlattening()

Disables automatic flattening for a specific map (e.g. when Address.City must not map to City).


Auto-flattening

When enabled, nested scalar properties can populate flat destination members:

// Entity.Address.City  →  FlatDto.City
CreateMap<Entity, FlatDto>();
  • Supports multi-level paths (e.g. A.B.C.Name → Name).
  • Ambiguous paths (multiple nested matches) throw MappingException — use explicit ForMember or disable flattening.
  • Works in runtime mapping, compiled maps, reverse maps, and ProjectTo.

How mapping works

  1. Create destination (parameterless constructor, or uninitialized object when none exists).
  2. BeforeMap hooks run.
  3. Compiled assignment (CompileToExisting) sets scalar and simple custom members.
  4. Post-compile runtime handles flatten-reverse members, complex custom MapFrom, nested objects, and collections.
  5. AfterMap hooks run.

Collections and nested objects are mapped at runtime using registered element/nested type maps. Flat scalars use compiled expressions for speed.


Collections

  • Different element types are mapped element-wise (never copied by reference).
  • Register CreateMap<TSourceElement, TDestinationElement> for each element pair.
  • Strings are not treated as collections.
CreateMap<OrderDto, OrderEntity>();
CreateMap<LineItemDto, LineItemEntity>();
// OrderDto.Lines → OrderEntity.Lines

Supported targets include List<T>, arrays, ICollection<T>, HashSet<T>, Queue<T>, and Stack<T>.


Mapping into an existing object

mapper.Map(orderDto, trackedEntity);

Use for EF updates: load the entity, map the DTO onto it.

  • Flattened reverse members (e.g. City → Address.City) are supported.
  • Collection properties are updated via nested mapping (not in the initial convention loop).
  • Ignored and explicit ForMember members are respected.

ProjectTo (database projection)

var dtos = dbContext.Orders
    .AsNoTracking()
    .ProjectTo<OrderEntity, OrderDto>(mapper)
    .ToList();
  • Builds a cached LINQ expression tree per type map (not per-row Map calls).
  • Works with EF Core for convention-based and flattening maps.
  • Simple computed MapFrom expressions (e.g. s => s.X * 2) can be included when translatable.
  • Throws MappingException at build time when a configured member cannot be translated.
  • Arbitrary method calls in MapFrom may build an expression that EF cannot translate to SQL — test your queries.

Prefer ProjectTo for list/query endpoints instead of loading entities and calling Map in memory.


Dependency injection

No changes required beyond registration:

services.AddSRSimpleMapper(cfg => cfg.RegisterProfile(new MyAppMappingProfile>());

ISRSimpleMapper is registered as singleton; MapperConfiguration and compiled maps are built once.


Entity Framework notes

  • Updates: Map(dto, trackedEntity) — do not create a new entity and attach.
  • Queries: Use ProjectTo with AsNoTracking() for read-only lists.
  • Owned types / nested value objects: Ensure your EF model matches flatten paths (e.g. OwnsOne(e => e.Address)).
  • Proxies: Nested mapping normalizes Castle.Proxies to base types when resolving nested maps.

Performance guidance

Scenario Recommendation
API list endpoints Paginate at the DB; use ProjectTo.
Flat DTOs Fast — compiled scalar mapping.
Nested graphs in memory Slower — reflection per object; fine for small/medium batches.
100k+ nested records Avoid mapping entire graphs in one shot; process in chunks.

Requirements checklist

  1. Register CreateMap<Source, Dest> for every pair you call Map with.
  2. Register element maps for collection properties with different element types.
  3. Use Ignore() for properties maintained elsewhere (passwords, manual navigations).
  4. Use ForMember / MapFrom for computed or renamed members.
  5. Use explicit ForMember or DisableAutoFlattening() when flatten paths are ambiguous.

Troubleshooting

Symptom Likely cause
No map found from X to Y Missing CreateMap<X, Y> for the exact CLR types.
Ambiguous flattening for member 'X' Multiple nested paths match; add explicit ForMember or disable flattening.
Cannot translate member 'X' to a database projection MapFrom cannot be expressed for ProjectTo; simplify or map in memory.
MappingException from MapFrom Null reference or invalid expression in custom mapping.
Collection empty Missing element CreateMap, or property ignored / skipped.
Reverse map missing nested value Ensure ReverseMap() is called; flattened reverse requires auto-flatten on forward map.
EF query fails after ProjectTo Expression uses non-translatable method calls; inspect SQL or simplify MapFrom.

License

MIT


Author

Shohanur Rahman
LinkedIn

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.8 64 9/21/2026
1.0.7 130 7/12/2026
1.0.6 142 7/5/2026
1.0.5 132 5/4/2026
1.0.4 108 5/3/2026

1.0.7: ReverseMap, multi-level auto-flattening, naming conventions, BeforeMap/AfterMap, SQL-friendly ProjectTo (cached expression trees), deep flatten and map-into-existing reverse-flatten fixes, ambiguous flatten errors, SourceMemberNaming, MappingException for failed MapFrom/ProjectTo. See PackageReleaseNotes.md.