Skip to content

Latest commit

 

History

History
63 lines (43 loc) · 3.14 KB

index.md

File metadata and controls

63 lines (43 loc) · 3.14 KB

DKNet.EfCore.DtoGenerator

Generate DTO property declarations and validate event payloads at compile time for .NET developers.

✨ Why use it?

  • Keep DTO property lists aligned with entities and inherited properties.
  • Apply local and project-wide property selection without repeating lists on every DTO.
  • Validate RaisesEvent declarations and generate convention-named payload records during compilation.

🚀 Quick Start

Use a .NET 10 console project. Install the packages, then replace Program.cs with the example.

dotnet new console -f net10.0 -n EfCoreDemo
cd EfCoreDemo
dotnet add package DKNet.EfCore.DtoGenerator
using DKNet.EfCore.DtoGenerator;

var dto = new ProductDto { Id = 1, Name = "Coffee", Price = 12m };
Console.WriteLine($"{dto.Name}: {dto.Price}"); // Coffee: 12

public sealed class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
}
[GenerateDto(typeof(Product))]
public partial record ProductDto;

Run with dotnet run.

🏗️ Architecture

The consuming compiler runs DtoGenerator and RaisesEventValidator with entity symbols, project analyzer options and the shared event name composer, emitting partial DTO and event source.

The generator is a netstandard2.0 analyzer running in the compiler process. The package compiles GenerateDtoAttribute source into the consuming assembly and exposes its MSBuild switches through buildTransitive props; generated types have no generator runtime service.

🔄 How it works

GenerateDto resolves the entity and partial shell, selects readable properties and emits init-only members, while conflicting filters skip that target with a diagnostic.

The source generator emits data properties, not mapping methods. Non-nullable strings become required; non-nullable collections shaped as an array, List<T>, IList<T>, ICollection<T> or IEnumerable<T> receive an = [] initializer (read-only and set collections do not), and retained complex references receive a null-forgiving initializer. Mapping remains the caller's responsibility.

🧩 Features

🔗 Related packages