ComnetSolution.AutoMapper
1.0.2
dotnet add package ComnetSolution.AutoMapper --version 1.0.2
NuGet\Install-Package ComnetSolution.AutoMapper -Version 1.0.2
<PackageReference Include="ComnetSolution.AutoMapper" Version="1.0.2" />
<PackageVersion Include="ComnetSolution.AutoMapper" Version="1.0.2" />
<PackageReference Include="ComnetSolution.AutoMapper" />
paket add ComnetSolution.AutoMapper --version 1.0.2
#r "nuget: ComnetSolution.AutoMapper, 1.0.2"
#:package ComnetSolution.AutoMapper@1.0.2
#addin nuget:?package=ComnetSolution.AutoMapper&version=1.0.2
#tool nuget:?package=ComnetSolution.AutoMapper&version=1.0.2
ComnetSolution.AutoMapper
A high-performance, open-source object-to-object mapper for .NET built on compiled LINQ expression trees.
Designed as a drop-in replacement for AutoMapper β migrate existing projects with minimal code changes.
Why ComnetSolution.AutoMapper?
AutoMapper became closed-source / commercial in recent versions. This library replicates the AutoMapper API surface you rely on β Profile, CreateMap, ForMember, ReverseMap, MapList, IMapper injection β without any licensing restrictions and with zero external dependencies beyond Microsoft.Extensions.DependencyInjection.Abstractions.
Key benefits:
- π Compiled expression trees β reflection cost paid once, subsequent maps run at near-native speed
- π Drop-in API β rename
AutoMapper.ProfileβMapperProfile,IMapperβIMapper - π Full DI integration β
AddMapper(...)or auto-discover profiles withAddMapperFromAssemblies(...) - π¦ Multi-target β supports .NET 6, 7, 8 and 10
- π‘οΈ MIT licensed β free for commercial and open-source use
Installation
dotnet add package ComnetSolution.AutoMapper
or via NuGet Package Manager:
Install-Package ComnetSolution.AutoMapper
Quick Start
1 β Define a Profile
using ComnetMapper.Configuration;
public class OrderProfile : MapperProfile
{
public OrderProfile()
{
CreateMap<Order, OrderDto>()
.ForMember(d => d.CustomerName, o => o.MapFrom(s => s.Customer.FullName))
.ForMember(d => d.InternalNote, o => o.Ignore()) // skip this property
.ReverseMap(); // also maps Dto β Order
}
}
2 β Register in DI (Program.cs / Startup.cs)
// Option A: list profiles explicitly
builder.Services.AddMapper(mapper =>
{
mapper.AddProfile<OrderProfile>();
mapper.AddProfile<CustomerProfile>();
});
// Option B: auto-discover every MapperProfile in the assembly
builder.Services.AddMapperFromAssemblies(typeof(Program).Assembly);
3 β Inject and Use
public class OrderService(IMapper mapper)
{
public OrderDto GetOrder(int id)
{
var order = _repo.FindById(id);
return mapper.Map<OrderDto>(order); // single object
}
public List<OrderDto> GetAll()
{
var orders = _repo.GetAll();
return mapper.MapList<Order, OrderDto>(orders).ToList();
}
}
API Reference
MapperProfile
| Method | Description |
|---|---|
CreateMap<TSource, TDest>() |
Registers a sourceβdestination mapping |
.ForMember(d => d.Prop, o => o.MapFrom(...)) |
Custom source expression for a member |
.ForMember(d => d.Prop, o => o.Ignore()) |
Exclude a destination member from mapping |
.BeforeMap((src, dest, mapper) => ...) |
Action to run before property assignment |
.AfterMap((src, dest, mapper) => ...) |
Action to run after property assignment |
.ReverseMap() |
Also registers the inverse (TDest β TSource) map |
IMapper
| Method | Description |
|---|---|
Map<TDest>(object source) |
Map to a new TDest instance |
Map<TSource, TDest>(source, destination) |
Map onto an existing TDest instance |
MapList<TSource, TDest>(IEnumerable<TSource>) |
Map a collection |
TryMap<TDest>(source, out MapResult<TDest>) |
Safe mapping β returns false + error instead of throwing |
DI Registration
| Extension | Description |
|---|---|
AddMapper(Action<Mapper>) |
Manual profile registration |
AddMapperFromAssemblies(params Assembly[]) |
Auto-discover all profiles in assemblies |
Advanced Examples
Before/After Map Hooks
CreateMap<User, UserDto>()
.BeforeMap((src, dest, mapper) =>
{
// Runs before any property is set β useful for validation
if (src.IsDeleted) throw new InvalidOperationException("Cannot map deleted user");
})
.AfterMap((src, dest, mapper) =>
{
// Runs after all properties β useful for computed values
dest.DisplayName = $"{dest.FirstName} {dest.LastName}".Trim();
});
Safe Mapping with TryMap
if (mapper.TryMap<OrderDto>(order, out var result))
{
return result.Value;
}
else
{
_logger.LogError("Mapping failed: {Error}", result.Error);
return null;
}
Auto-Discover Profiles
// Scans the entire application assembly for MapperProfile subclasses
builder.Services.AddMapperFromAssemblies(
typeof(Program).Assembly,
typeof(SharedProfile).Assembly // include other assemblies if needed
);
Reverse Map
CreateMap<CreateOrderRequest, Order>().ReverseMap();
// Now both directions work:
var order = mapper.Map<Order>(request);
var request = mapper.Map<CreateOrderRequest>(order);
Migration from AutoMapper
| AutoMapper | ComnetMapper |
|---|---|
using AutoMapper; |
using ComnetMapper.Configuration; |
Profile |
MapperProfile |
IMapper |
IMapper |
services.AddAutoMapper(...) |
services.AddMapper(...) |
mapper.Map<TDest>(source) |
β same |
mapper.Map<TSource, TDest>(source, dest) |
β same |
CreateMap<A, B>() |
β same |
ForMember(d => d.X, o => o.MapFrom(...)) |
β same |
ForMember(d => d.X, o => o.Ignore()) |
β same |
.ReverseMap() |
β same |
Supported Type Conversions
The mapper handles the following automatically (no configuration needed):
- Same-type assignment
- Widening:
T β T?(e.g.int β int?) - Narrowing:
T? β T(returnsdefaultwhen null) - Numeric conversions (
int β long,float β double, etc.) - Enum β enum, enum β numeric
- Implicit / explicit conversion operators
IEnumerable<TSrc>βIList<TDest>(element-wise mapping)- Nested complex objects (recursively mapped)
Project Structure
ComnetMapper/
βββ src/
β βββ ComnetMapper/
β βββ Abstractions/
β β βββ IMapper.cs # Public interface + MapResult<T>
β βββ Configuration/
β β βββ MapperProfile.cs # Profile base class + fluent API
β βββ Core/
β β βββ Mapper.cs # Engine: expression compilation + caching
β βββ Extensions/
β β βββ MapperServiceExtensions.cs # IServiceCollection extensions
β β βββ MapperExtensions.cs # for common methods.
β βββ ComnetMapper.csproj
βββ README.md
βββ LICENSE
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
- Fork the repo
- Create a feature branch:
git checkout -b feature/your-feature - Commit your changes and push
- Open a pull request against
main
License
MIT β see LICENSE for full text.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 is compatible. 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. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
-
net10.0
-
net6.0
-
net7.0
-
net8.0
-
net9.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.