RSCG – Najlot.Audit.SourceGenerator
| name | Najlot.Audit.SourceGenerator |
| nuget | https://www.nuget.org/packages/Najlot.Audit.SourceGenerator/ |
| link | https://github.com/najlot/Audit |
| author | Najlot |
Generates audit/change-tracking code at compile time — detects which properties changed between two snapshots of an object.
How to use
1. Mark your entity and a partial provider with [AuditProvider]:
“`charp
[AuditProvider]
public partial class Person
{
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public int Id { get; set; }
}
[AuditProvider]
public partial class PersonAuditProvider
{
[AuditIgnore(nameof(Person.Id))]
public static partial IEnumerable
}
“`
2. Take a snapshot, mutate, then get changes:
“`charp
var audit = new Audit();
audit.RegisterProvider
var snapshot = audit.CreateSnapshot(p);
p.LastName = “Ignat”;
foreach (var change in snapshot.GetChanges())
Console.WriteLine($”{change.Path}: {change.OldValue} → {change.NewValue}”);
“`
You can use for Property-level change tracking / audit logs at compile time.
Supports [AuditIgnore] to exclude properties.
This is how you can use Najlot.Audit.SourceGenerator .
The code that you start with is
<project sdk="Microsoft.NET.Sdk">
<propertygroup>
<outputtype>Exe</outputtype>
<targetframework>net10.0</targetframework>
<implicitusings>enable</implicitusings>
<nullable>enable</nullable>
</propertygroup>
<itemgroup>
<packagereference version="0.0.1" include="Najlot.Audit">
<packagereference version="0.0.1" include="Najlot.Audit.SourceGenerator">
</packagereference>
<propertygroup>
<emitcompilergeneratedfiles>true</emitcompilergeneratedfiles>
<compilergeneratedfilesoutputpath>$(BaseIntermediateOutputPath)\GX</compilergeneratedfilesoutputpath>
</propertygroup>
</packagereference>
The code that you will use is
using AuditDemo;
using Najlot.Audit;
Person p = new() { Id = 1, FirstName = "John", LastName = "Doe" };
var audit = new Audit();
audit.RegisterProvider<personauditprovider>();
var snapshot = audit.CreateSnapshot(p);
p.LastName = "Ignat";
p.FirstName = "Andrei";
var changes= snapshot.GetChanges().ToArray();
foreach (var change in changes)
{
Console.WriteLine($"Property: {change.Path}, Old Value: {change.OldValue}, New Value: {change.NewValue}");
}
using Najlot.Audit;
using Najlot.Audit.Attributes;
namespace AuditDemo;
[AuditProvider]
public partial class Person
{
public string FirstName { get; set; }= string.Empty;
public string LastName { get; set; }= string.Empty;
public string FullName() => $"{FirstName} {LastName}";
public int Id { get; set; }
}
[AuditProvider]
public partial class PersonAuditProvider
{
[AuditIgnore(nameof(Person.Id))]
public static partial IEnumerable<propertyvalue> GetPropertyValues(Person entity);
}
The code that is generated is
// <auto-generated>
#nullable enable
namespace AuditDemo
{
public partial class PersonAuditProvider
{
public static partial global::System.Collections.Generic.IEnumerable<global::najlot.audit.propertyvalue> GetPropertyValues(global::AuditDemo.Person entity)
{
yield return new global::Najlot.Audit.PropertyValue("FirstName", entity.FirstName);
yield return new global::Najlot.Audit.PropertyValue("LastName", entity.LastName);
}
}
}
// <auto-generated>
#nullable enable
using Najlot.Audit;
namespace AuditDemo
{
public static class AuditRegistrationExtensions_AuditDemo
{
public static global::Najlot.Audit.IAudit RegisterAuditDemoAuditProviders(this global::Najlot.Audit.IAudit audit)
{
audit.Register<global::auditdemo.person>(global::AuditDemo.PersonAuditProvider.GetPropertyValues);
return audit;
}
}
}
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Najlot.Audit.SourceGenerator