A simple and lightweight .NET object mapping library. MapOnly provides easy-to-use APIs for converting objects between different types with minimal configuration.
$ dotnet add package MapOnlyMapOnly is a simple and lightweight .NET library for object-to-object mapping. If you need a straightforward library focused solely on mapping without extra complexity, MapOnly is the perfect choice for you.
# Using .NET CLI
dotnet add package MapOnly
# Using Package Manager Console
Install-Package MapOnly
# Or search "MapOnly" in NuGet Package Manager
For simple object mapping where properties have the same names:
using MapOnly;
// Map using the new instance creation overload (recommended)
var userDto = user.Map<User, UserDto>();
// Or if you need to map to an existing instance
var existingDto = new UserDto();
user.Map(existingDto);
For custom mappings, configure once at application startup:
// At application startup
MapExtension.Create<User, UserDto>()
.Add(u => u.FullName, dto => dto.DisplayName)
.Ignore(dto => dto.InternalField);
// Then use throughout your application
var userDto = user.Map<User, UserDto>();
This method creates a mapping configuration between two classes. If the classes have the same property names, automatic mapping will work without configuration.
using MapOnly;
MapExtension.Create<SourceClass, DestinationClass>()
MapExtension.Create<UserViewModel, User>()
For properties with different names or when you need to set constant values, use the Add method.
using MapOnly;
// Map properties with different names
MapExtension.Create<SourceClass, DestinationClass>()
.Add(source => source.Property1, dest => dest.Property2);
// Set a constant value
MapExtension.Create<SourceClass, DestinationClass>()
.Add(dest => dest.Property1, "ConstantValue");
MapExtension.Create<UserViewModel, User>()
.Add(v => v.DisplayName, u => u.FullName)
.Add(u => u.CreatedBy, "Admin");
Use this method to exclude properties from mapping.
using MapOnly;
MapExtension.Create<SourceClass, DestinationClass>()
.Ignore(dest => dest.Property1);
MapExtension.Create<UserViewModel, User>()
.Add(x => x.Birthday, a => a.UpdatedDate)
.Ignore(u => u.CreatedDate)
.Ignore(u => u.CreatedUser)
.Ignore(u => u.IsActive)
.Ignore(u => u.UpdatedDate)
.Ignore(u => u.UpdatedUser);
Converts one object to another following configured or automatic mappings.
// Recommended: Automatically create destination instance
var destination = source.Map<SourceClass, DestinationClass>();
// Alternative: Map to existing instance (useful when updating objects)
var destination = new DestinationClass();
source.Map(destination);
// Simple mapping - automatically creates UserViewModel instance
var viewModel = user.Map<User, UserViewModel>();
// Map collections
var userViewModels = users
.Select(u => u.Map<User, UserViewModel>())
.ToList();
// Map to existing instance (e.g., updating an entity)
var existingUser = GetUserFromDatabase(id);
userViewModel.Map(existingUser);
SaveChanges();
You can also use attributes to control mapping behavior:
public class MyClass
{
public int Id { get; set; }
[MapAttribute(Ignored = true)]
public string InternalProperty { get; set; }
}
Configure your mappings once at application startup. MapOnly uses a static configuration that persists throughout your application's lifetime.
Program.cs or Startup.cs:
// Program.cs (.NET 6+)
var builder = WebApplication.CreateBuilder(args);
// Configure MapOnly mappings
ConfigureMappings();
var app = builder.Build();
app.Run();
static void ConfigureMappings()
{
MapExtension.Create<User, UserDto>()
.Add(u => u.FullName, dto => dto.DisplayName)
.Ignore(dto => dto.CreatedDate);
MapExtension.Create<Product, ProductDto>()
.Ignore(dto => dto.InternalId);
}
Or create a dedicated configuration class:
// MappingConfiguration.cs
public static class MappingConfiguration
{
public static void Configure()
{
ConfigureUserMappings();
ConfigureProductMappings();
}
private static void ConfigureUserMappings()
{
MapExtension.Create<User, UserDto>()
.Add(u => u.FullName, dto => dto.DisplayName)
.Ignore(dto => dto.CreatedDate);
}
private static void ConfigureProductMappings()
{
MapExtension.Create<Product, ProductDto>()
.Ignore(dto => dto.InternalId);
}
}
// Program.cs
MappingConfiguration.Configure();
Global.asax.cs:
protected void Application_Start()
{
// Other configurations...
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
// Configure MapOnly
MappingConfiguration.Configure();
}
Program.cs:
static class Program
{
[STAThread]
static void Main()
{
// Configure mappings at startup
MappingConfiguration.Configure();
// Rest of your application
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
source.Map<TSource, TDest>() over source.Map(new TDest())// ✅ Recommended
var dto = user.Map<User, UserDto>();
// ❌ Less efficient (creates instance before calling Map)
var dto = user.Map(new UserDto());
// ✅ Good - when you need to update an existing instance
var existingEntity = repository.Get(id);
dto.Map(existingEntity);
repository.Update(existingEntity);
MIT License - See LICENSE.txt for details
Contributions are welcome! Please feel free to submit a Pull Request.