Mapster: a C# object-to-object mapper that generates DTOs and mapping code
A fast, fun and stimulating object to object Mapper
At a glance
- What is it?
- Mapster maps objects in C# and can generate DTO classes and mapper code from attributes. It is aimed at .NET teams that want mapping handled by the library rather than by hand, and it ships under the MIT licence.
- Who is it for?
- Adopt Mapster if your project is C# and you want mapping handled by Adapt, ProjectToType and optional code generation instead of hand-written mapping methods. Do not adopt it if your stack is not .NET, or if you need an officially supported migration path from another mapper: the README states the IMapper signature is compatible, but it does not document rollback.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Mapster solves, and for whom
Mapster addresses a narrow, repetitive job in .NET code: moving values from one object type to another. The README states the premise directly: "Writing mapping methods is a machine job. Do not waste your time, let Mapster do it." That sentence is the whole pitch.
The audience is C# developers who maintain DTOs, view models or persistence models next to their domain types. Those developers either write the assignment code by hand, or they take a mapping library. Mapster sits in the second group. The repository is written in C#, published under the MIT licence, and the README points readers to a documentation site at mapstermapper.github.io for the deeper articles.
The project is not archived and its last push was on 2026-09-22, the same date as the v10.0.13 release. That is a signal about the current state of the repository, not a quality claim; the README's own evidence for the design goal is a benchmark project in src/Benchmark, which a reader can open rather than take on trust.
Adapt, ProjectToType and the generated mapper classes
The runtime mechanism is an extension method named Adapt. When you call sourceObject.Adapt<Destination>(), Mapster creates the destination object and maps values to it. When you call sourceObject.Adapt(destObject), you create the object and Mapster writes into it. The README presents these as the two basic usage shapes, and the difference matters: the first allocates, the second reuses.
The second mechanism is query projection. Mapster provides extensions to map queryables, and the README shows context.Sources.ProjectToType<Destination>().ToList() as the alternative to a hand-written Select that assigns Id, Name, Surname and so on. Because this builds a Select expression from the DTO, the projection is expressed in the query rather than applied after materialisation. The README does not spell out how a given provider translates that expression, so the correctness of the generated SQL is something a reader has to check against their own context.
The third mechanism is generation. Mapster.Tool takes an attribute such as [AdaptTo("[name]Dto"), GenerateMapper] on a class and produces a DTO plus a static mapper class. The README shows the generated surface: an AdaptToDto extension, an AdaptTo overload that fills an existing DTO, and a ProjectToDto expression property. That is the part of the library that removes the DTO classes from your source tree entirely, and it is why the topics list includes codegenerator alongside mapper.
Installing Mapster and mapping a first object
The README gives two install paths. With the NuGet CLI you run Install-Package Mapster. With the .NET CLI you run the following, substituting your project name:
dotnet add package Mapster --project <PROJECT_NAME>After the package restores, the smallest working call is the Adapt extension on the source instance. The README's example is one line:
var destObject = sourceObject.Adapt<Destination>();You should see a Destination instance whose properties were populated from sourceObject, with no mapping method written by you.
If you want the mapper injected rather than called as an extension, the README says to add Mapster to the service collection:
services.AddMapster();The README states that you can then take an IMapper through dependency injection, and that this is the point where code migrating from AutoMapper does not have to change. The README's sample constructor takes IMapper and calls mapper.Adapt<Destination>(). Note that the README does not show a separate registration call for the mapper itself; AddMapster is the only line given.
For query projection against a DbContext, the README's example is:
var destinations = context.Sources.ProjectToType<Destination>().ToList();That replaces a hand-written Select that assigns each property. If you then want generated DTOs and mapper classes, the README points to Mapster.Tool as a separate dotnet tool, and the attribute is applied to the source class rather than to a configuration file:
[AdaptTo("[name]Dto"), GenerateMapper]
public class Student {
...
}Where the README leaves you on your own
The README is a front door, not a manual. It lists the packages (Mapster, Mapster.Core, Mapster.DependencyInjection, Mapster.EFCore, Mapster.EF6, Mapster.JsonNet, Mapster.Immutable, Mapster.Diagnostics, ExpressionDebugger) and the Mapster.Tool dotnet tool, but it does not explain when to choose Mapster.Core over Mapster, or what Mapster.Diagnostics adds. A reader who needs those answers has to open the documentation site.
The migration claim deserves scrutiny. The README says you can take an IMapper via dependency injection "so you do not have to change code, when migrating to mapster from automapper". That is a statement about the interface shape, not about behaviour. Two libraries can both expose IMapper and still differ in how they treat nulls, nested members, collections or unmapped properties. The README does not document rollback, and it does not list the behavioural differences you would hit. If you are moving an existing codebase, the compatibility of the type name is the beginning of the work, not the end.
The generation path also has a cost the README does not discuss. Once StudentDto and StudentMapper are generated from attributes, the generated types are part of your build output. The README does not say how the tool handles a hand-edited generated file, or what happens when an attribute is removed. That is a gap a team adopting Mapster.Tool will meet on the first refactor.
Finally, the performance claim is stated but not substantiated in the README text. It says Mapster "was designed to be efficient on both speed and memory" and points at src/Benchmark. The repository includes a benchmark project; the README does not print its numbers. Treat the claim as a pointer to a project you can run, not as a result.
Mapster versus AutoMapper and Mapperly
The two alternatives that come up most often in search are AutoMapper and Mapperly, and the three take different routes to the same destination.
AutoMapper is the incumbent. Its configuration is profile-based, and mapping rules live in classes you write and register. Mapster's README leans on that familiarity: it ships an IMapper injection path so the call site can stay the same. The practical difference is where the rules live. AutoMapper keeps them in profiles; Mapster's README shows rules expressed through the Adapt call, through attributes on the source type, or through the settings articles it links to. If your team already has a large profile set, that set is the migration cost.
Mapperly is a source generator. It emits the mapping code at compile time, and the generated code is what runs. Mapster.Tool is also a generator, but it is a separate dotnet tool invoked to produce DTOs and mapper classes, and the README presents the attribute-driven path as the way to get explicit mapping. If your reason for choosing a generator is that you want to read the emitted code in your own project and step through it, that is a different workflow from calling Adapt at runtime, and it is worth deciding which one you actually want before picking a library.
Manual mapping is the third option, and the README's own ProjectToType example frames the trade honestly: the alternative to the extension is a Select that assigns each property by hand. Manual mapping is verbose and it is also the only version where nothing is inferred. Mapster removes the verbosity; it also removes the explicit list, which is exactly the list you read when you want to know what a mapping does.
Licence, releases and the cost of keeping up
Mapster is MIT licensed, and the LICENSE file sits at the repository root. For most teams that is the permissive case: you can use, modify and redistribute the library, and you keep your own source. This is a description of the licence identifier, not legal advice; if your organisation has rules about third-party dependencies, the MIT text in LICENSE is what your reviewer will read.
The release cadence is visible in the tags. v10.0.13 was pushed on 2026-09-22, v10.0.12 on 2026-08-19, and v10.0.13-pre02 on 2026-08-25. That is a stream of patch releases with pre-release versions appearing between them. The practical cost is not the upgrade itself, which for a patch bump is usually a package version change, but the surface area you are tracking: the README lists nine packages plus a dotnet tool, and each has its own stable and pre-release line.
Two habits follow from that. Pin the versions you depend on rather than floating, so a pre-release tag cannot reach a build by accident. And when you upgrade, check the release notes on the GitHub releases page, which the README links for the "several fixes" entry, rather than assuming a patch bump is inert. The README does not describe a deprecation policy or a support window for older major versions, so an upgrade that crosses a major boundary is a change you plan for rather than one you schedule.
Editorial conclusion
Adopt Mapster if your project is C# and you want mapping handled by Adapt, ProjectToType and optional code generation instead of hand-written mapping methods. Do not adopt it if your stack is not .NET, or if you need an officially supported migration path from another mapper: the README states the IMapper signature is compatible, but it does not document rollback. Before committing, verify the Mapster package version on NuGet, check whether you need Mapster.Tool or only the runtime package, and confirm that Queryable Extensions behave as you expect against your own DbContext.
Frequently asked questions
What does Mapster do?
Mapster maps values from one object to another in C#. The README's basic examples are sourceObject.Adapt<Destination>(), which creates the destination, and sourceObject.Adapt(destObject), which maps into an object you created. It also provides queryable extensions such as ProjectToType and a Mapster.Tool dotnet tool that generates DTOs and mapper classes.
Is Mapster free to use?
Yes. The repository is published under the MIT licence, and the LICENSE file is at the repository root. The packages are distributed through NuGet, as shown in the README's package table.
Is Mapster faster than AutoMapper?
The README states that Mapster was designed to be efficient on both speed and memory, and it points to a benchmark project in src/Benchmark. The README itself does not print comparison numbers, so the claim is something you would verify by running that project rather than by reading the page.
how to use mapster in c#
Install the Mapster package with dotnet add package Mapster --project <PROJECT_NAME>, then call sourceObject.Adapt<Destination>() to create a destination object or sourceObject.Adapt(destObject) to map into an existing one. For query projection, the README shows context.Sources.ProjectToType<Destination>().ToList().
how to use mapster in asp net core
Add Mapster to the service collection with services.AddMapster(), then take an IMapper through dependency injection and call mapper.Adapt<Destination>(). The README presents this injection path as the way to keep call sites unchanged when migrating from another mapper.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mapstermapper-mapster)