dotnet-mapping-standard
Skill4 starsChanged 10 months agoMITView on GitHub
Use when mapping between DTOs, contracts, and persistence models in .NET - prefer source-generated mappers with explicit boundary conversions over reflection-based mapping.
In this repository67 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- agents-onboardingSkill
- agent-workitem-automationSkill
- architecture-testingSkill
- aspire-integration-testingSkill
- automated-standards-enforcementSkill
- best-practice-introductionSkill
- branching-strategy-and-conventionsSkill
- broken-windowSkill
- change-risk-rollbackSkill
- ci-cd-conformanceSkill
- component-boundary-ownershipSkill
- contract-consistency-validationSkill
- csharp-best-practicesSkill
- deployment-provenanceSkill
- documentation-as-codeSkill
- documentation-scaffoldSkill
- dotnet-bespoke-code-minimisationSkill
- dotnet-best-practicesSkill
- dotnet-domain-primitivesSkill
- dotnet-efcore-practicesSkill
- dotnet-healthchecksSkill
- dotnet-logging-serilogSkill
- dotnet-open-source-first-governanceSkill
- dotnet-source-generation-firstSkill
- dotnet-specification-patternSkill
- dotnet-testing-assertionsSkill
- environment-traceabilitySkill
- finishing-a-development-branch-iddSkill
- greenfield-baselineSkill
- impacted-scope-enforcementSkill
- incremental-change-impactSkill
- incremental-deploymentSkill
- innersource-governance-bootstrapSkill
- issue-driven-deliverySkill
- library-extraction-stabilisationSkill
- local-dev-experienceSkill
- markdown-authorSkill
- modern-csharp-coding-standardsSkill
- monorepo-orchestration-setupSkill
- observability-logging-baselineSkill
- pair-programmingSkill
- persona-switchingSkill
- process-skill-routerSkill
- quality-gate-enforcementSkill
- release-tagging-planSkill
- repo-best-practices-bootstrapSkill
- repository-foundation-bootstrapSkill
- requirements-gatheringSkill
- runtime-tooling-validationSkill
- safe-brownfield-refactorSkill
- scoped-colocationSkill
- security-processesSkill
- selective-build-testSkill
- semantic-version-impactSkill
- session-awareSkill
- skills-first-workflowSkill
- static-analysis-securitySkill
- structured-review-workflowSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 8 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 29
Apply DI gating rules: Use static mappers unless mapper has injected dependencies
- Distinctive: line 31
Verify side-effect free: Ensure mappings have no side effects or external calls
- Distinctive: line 37
Prefer open-source, source-generated mapping tools.
- Distinctive: line 62
Prefer projection mappings that avoid materialising large object graphs when not needed.
- Distinctive: line 63
Keep read models separate where pragmatic.
- Very specific: line 74
If a mapper is injected into a constructor (controller/handler/service), reviewers must check whether the mapper implementation itself has …
- Distinctive: line 76
If the mapper has no injected dependencies (pure/stateless mapping), require refactor to a static mapper and remove DI registration.
- Distinctive: line 133
When reviewing mappers registered in DI:
- Distinctive: line 139
NO: Remove unused dependencies
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Overview
Standardise mapping between DTOs, domain models, and persistence models using source-generated mappers. Mappings live at explicit boundaries (API, infrastructure) with deterministic, testable conversion paths and no runtime reflection magic.
When to Use
- Mapping between API request/response DTOs and domain models
- Converting domain entities to/from persistence models
- Handling integration event contracts at service boundaries
- Reviewing PRs that introduce new mapping logic
- Refactoring existing reflection-based mappers to source-generated alternatives
Core Workflow
- Identify mapping boundaries: Locate where DTOs cross into domain or persistence layers
- Choose source-generated mapper: Select Mapperly or similar compile-time mapper
- Create explicit mappers: Implement mapper classes at boundary projects (API, Infrastructure)
- Handle typed IDs explicitly: Map strongly typed IDs and value objects with explicit conversions
- Apply DI gating rules: Use static mappers unless mapper has injected dependencies
- Add mapping tests: Include round-trip tests for critical boundary conversions
- Verify side-effect free: Ensure mappings have no side effects or external calls
Core
Defaults
- Prefer open-source, source-generated mapping tools.
- Mappings live at boundaries (API project, Infrastructure project), not scattered across the domain.
- Typed IDs and value objects must be mapped explicitly (see
dotnet-domain-primitives).
Anti-patterns to avoid
- Reflection-based "magic mapping" that fails at runtime.
- Mapping logic embedded inside domain entities.
- Implicit conversions that obscure boundary crossings.
Review rules
- New DTO/domain/persistence types must have deterministic, testable mapping paths.
- Mapping must be side-effect free.
Load: examples
- API: map request DTO -> command with explicit typed ID parsing/creation.
- Persistence: map EF entity -> domain aggregate using explicit value object construction.
- Integration: map external event contract -> internal event with boundary validations.
Load: advanced
Projections / query scenarios
- Prefer projection mappings that avoid materialising large object graphs when not needed.
- Keep read models separate where pragmatic.
Error strategy
- Invalid boundary inputs fail fast at the boundary (validation).
- Domain invariants enforced by constructors/factories.
Load: enforcement
Review heuristic: mapper DI gating
- If a mapper is injected into a constructor (controller/handler/service), reviewers must check whether the mapper implementation itself has injected dependencies.
- If the mapper has no injected dependencies (pure/stateless mapping), require refactor to a static mapper and remove DI registration.
- Injection is permitted only when mapping depends on external collaborators and those collaborators are injected into the mapper.
- "Inject for testability" is not sufficient when mapping is deterministic; test the mapper directly.
- Reject PRs introducing runtime reflection mapping unless justified per
dotnet-source-generation-first. - Require mapping tests for critical boundary conversions (typed IDs and value objects).
Load: testing
Mapping Unit Test Template
public class OrderMapperTests
{
[Fact]
public void ToEntity_WithValidDto_MapsAllProperties()
{
// Arrange
var dto = new CreateOrderRequest
{
CustomerId = "cust-123",
Amount = 99.99m,
Currency = "GBP"
};
// Act
var entity = OrderMapper.ToEntity(dto);
// Assert
entity.CustomerId.Value.Should().Be("cust-123");
entity.Amount.Value.Should().Be(99.99m);
entity.Amount.Currency.Should().Be(Currency.GBP);
}
[Fact]
public void ToDto_RoundTrip_PreservesData()
{
// Arrange
var original = new Order(
CustomerId.From("cust-123"),
Money.From(99.99m, Currency.GBP));
// Act
var dto = OrderMapper.ToDto(original);
var roundTripped = OrderMapper.ToEntity(dto);
// Assert
roundTripped.Should().BeEquivalentTo(original);
}
}DI Gating Checklist
When reviewing mappers registered in DI:
- Does the mapper have zero injected dependencies?
- YES: Refactor to static mapper, remove DI registration
- NO: Proceed to next check
- Are all injected dependencies used during mapping?
- NO: Remove unused dependencies
- YES: Proceed
- Is injection for "testability only"?
- YES: Reject - test static mappers directly
- NO: Injection acceptable
Red Flags - STOP
These statements indicate mapping anti-patterns:
| Thought | Reality |
| "AutoMapper conventions will handle it" | Explicit mapping prevents runtime surprises; be deliberate |
| "Mapping logic belongs in the entity" | Keep entities clean; mappers handle boundary concerns |
| "Inject the mapper for testability" | Pure mappers don't need DI; test static mappers directly |
| "Runtime reflection is fine" | Source-generated mappers are faster and fail at compile time |
| "Implicit conversions are convenient" | Explicit conversions make boundary crossings visible |
| "Round-trip tests aren't worth it" | Round-trip tests catch subtle mapping bugs; always include them |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

