chore: initial commit
Signed-off-by: Alan Brault <alan.brault@visus.io>
This commit is contained in:
117
README.md
Normal file
117
README.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Mapper Source Generator Example
|
||||
|
||||
This project demonstrates how you can use incremental source generators in C# to generate domain transfer objects (DTOs)
|
||||
and mapping classes from a POCO.
|
||||
|
||||
> [!WARNING]
|
||||
> This is a sample project and not intended for production use. It is meant to illustrate the concept of using source generators.
|
||||
> Please look into using either [mapster's](https://github.com/MapsterMapper/Mapster) code generator or [mapperly](https://github.com/riok/mapperly) instead.
|
||||
|
||||
## Requirements
|
||||
- .NET 8.0 SDK
|
||||
|
||||
## What's Included
|
||||
- `MapperSourceGen`: The main project that contains the attributes for decorating classes and properties for the source generator.
|
||||
- `MapperSourceGen.Sample`: A sample class library that demonstrates the use of the source generator.
|
||||
- `MapperSourceGen.SourceGenerator`: The source generator that generates DTOs and mapping classes.
|
||||
- `MapperSourceGen.SourceGenerator.Tests`: Unit tests for the source generator to ensure it works as expected (snapshot testing).
|
||||
|
||||
Feel free to inspect the `.csproj` files for the projects to see how they are set up and how the source generator is integrated.
|
||||
|
||||
> [!NOTE]
|
||||
> The source files emitted by the source generator will be under `Dependencies -> .NET 8.0 -> Source Generators` in the `MapperSourceGen.Sample` project if using Rider.
|
||||
|
||||
## Purpose
|
||||
|
||||
As projects grow, the need for transferring data between layers (like from a database to a UI) becomes essential.
|
||||
However, with that comes the additional complexity of maintaining DTOs and mapping classes. One of the ways this can be
|
||||
solved is by using source generators to automate the creation of these classes.
|
||||
|
||||
Source generators provide the ability to generate code at compile time, which can help reduce boilerplate code and improve maintainability
|
||||
and reduce the reliance on expensive reflection-based mapping.
|
||||
|
||||
## How It Works
|
||||
|
||||
The project **MapperSourceGen.SourceGenerator** contains a source generator that scans for classes decorated with the `GenerateMapperAttribute`.
|
||||
When it finds such a class, it generates a DTO and a mapping class for it.
|
||||
|
||||
### Example
|
||||
|
||||
Let's say you have a class `Order` that you want to generate a DTO and mapping class for. You would decorate it with the `GenerateMapperAttribute` like this:
|
||||
|
||||
**Order.cs**
|
||||
```csharp
|
||||
[Mapper]
|
||||
public sealed class Order
|
||||
{
|
||||
[MapAlias("EntityId")] // renames Id to EntityId in the DTO
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid? CustomerId { get; set; }
|
||||
|
||||
[MapAlias("OrderId")] // renames IncrementId to OrderId in the DTO
|
||||
public int IncrementId { get; set;}
|
||||
|
||||
public DateTimeOffset Created { get; set;}
|
||||
|
||||
public DateTimeOffset? Updated { get; set; }
|
||||
|
||||
[MapIgnore] // this property will not be included in the DTO or mapper
|
||||
public string TransactionId { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
The source generator will then generate a DTO class `OrderDto` and a mapping class `OrderMapper` that looks like this:
|
||||
|
||||
**OrderMapper.g.cs**
|
||||
```csharp
|
||||
public sealed partial class OrderMapper
|
||||
{
|
||||
public static Order ToModel(OrderDto source)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
return new Order()
|
||||
{
|
||||
Id = source.EntityId,
|
||||
CustomerId = source.CustomerId,
|
||||
IncrementId = source.OrderId
|
||||
Created = source.Created,
|
||||
Updated = source.Updated
|
||||
}
|
||||
}
|
||||
|
||||
public static OrderDto ToDto(Order source)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
return new OrderDto()
|
||||
{
|
||||
EntityId = source.Id,
|
||||
CustomerId = source.CustomerId,
|
||||
OrderId = source.IncrementId,
|
||||
Created = source.Created,
|
||||
Updated = source.Updated
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**OrderDto.g.cs**
|
||||
```csharp
|
||||
public sealed partial class OrderDto
|
||||
{
|
||||
public Guid? CustomerId { get; set; }
|
||||
|
||||
public Guid EntityId { get; set; }
|
||||
|
||||
public int OrderId { get; set; }
|
||||
|
||||
public DateTimeOffset Created { get; set; }
|
||||
|
||||
public DateTimeOffset? Updated { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user