Dhazel.Revertibles.Mvvm
1.1.0
dotnet add package Dhazel.Revertibles.Mvvm --version 1.1.0
NuGet\Install-Package Dhazel.Revertibles.Mvvm -Version 1.1.0
<PackageReference Include="Dhazel.Revertibles.Mvvm" Version="1.1.0" />
<PackageVersion Include="Dhazel.Revertibles.Mvvm" Version="1.1.0" />
<PackageReference Include="Dhazel.Revertibles.Mvvm" />
paket add Dhazel.Revertibles.Mvvm --version 1.1.0
#r "nuget: Dhazel.Revertibles.Mvvm, 1.1.0"
#:package Dhazel.Revertibles.Mvvm@1.1.0
#addin nuget:?package=Dhazel.Revertibles.Mvvm&version=1.1.0
#tool nuget:?package=Dhazel.Revertibles.Mvvm&version=1.1.0
Dhazel.Revertibles
.NET utilities for property change tracking: detect dirty state, revert to pristine values, and accept changes as the new baseline.
Projects
| Project | Description |
|---|---|
Dhazel.Revertibles |
Core change-tracking API |
Dhazel.Revertibles.Generators |
Source generator + analyzers for [RevertibleObject] |
Dhazel.Revertibles.Mvvm |
MVVM integration (RevertibleValidator + CommunityToolkit.Mvvm) |
Dhazel.TestHelpers |
Shared test helpers |
Dhazel.Revertibles.Tests |
Unit tests for Revertibles |
Dhazel.Revertibles.Generators.Tests |
Unit tests for the generator and analyzers |
Dhazel.Revertibles.Mvvm.Tests |
Unit tests for Mvvm |
Requirements
- .NET 10
Install
dotnet add package Dhazel.Revertibles
dotnet add package Dhazel.Revertibles.Mvvm
Usage
All patterns share the same API:
| Method | Description |
|---|---|
HasChanged() / HasChanged("Prop") |
Whether any (or a specific) tracked property differs from its pristine value |
Revert() / Revert("Prop") |
Restore all (or a specific) tracked properties to pristine values |
AcceptChanges() / AcceptChanges("Prop") |
Snapshot current values as the new pristine baseline |
1. Attribute + Revertible.Track
Decorate properties with [Revertible], then track any instance:
using Dhazel.Revertibles;
public class Person
{
[Revertible]
public int Id { get; set; }
[Revertible]
public string? Name { get; set; }
}
var person = new Person { Id = 1, Name = "Ada" };
var revertible = Revertible.Track(person);
person.Name = "Grace";
revertible.HasChanged(); // true
revertible.HasChanged("Name"); // true
revertible.Revert("Name");
// person.Name == "Ada"
person.Name = "Grace";
revertible.AcceptChanges();
// "Grace" is now the pristine value
2. Inherit AbstractRevertible
When the type itself should be revertible:
using Dhazel.Revertibles;
public class Person : AbstractRevertible
{
[Revertible]
public int Id { get; set; }
[Revertible]
public string? Name { get; set; }
}
var person = new Person { Id = 1, Name = "Ada" };
person.Name = "Grace";
person.HasChanged(); // true
person.Revert(); // Name restored to "Ada"
3. Third-party / undecorated types
Track objects you cannot annotate (or choose not to) with WithProperties:
using Dhazel.Revertibles;
// No [Revertible] attributes on this type
public class ExternalDto
{
public int Id { get; set; }
public string? Name { get; set; }
}
var dto = new ExternalDto { Id = 1, Name = "Ada" };
var revertible = Revertible.Track(dto)
.WithProperties(["Id", "Name"]);
dto.Name = "Grace";
revertible.HasChanged("Name"); // true
revertible.Revert(); // restored
4. MVVM with RevertibleValidator
Combine change tracking with CommunityToolkit.Mvvm source generators:
using CommunityToolkit.Mvvm.ComponentModel;
using Dhazel.Revertibles.Mvvm.ObservableValidators;
using Dhazel.Revertibles;
public partial class PersonViewModel : RevertibleValidator
{
[ObservableProperty]
[property: Revertible]
private int _id;
[ObservableProperty]
[property: Revertible]
private string? _name;
}
var vm = new PersonViewModel { Id = 1, Name = "Ada" };
vm.Name = "Grace";
vm.HasChanged(); // true
vm.Revert(); // Name restored to "Ada"
5. [RevertibleObject] — zero-boilerplate codegen
Skip the base class and manual wiring entirely. Decorate any partial class with [RevertibleObject], and mark the properties to track with [Revertible].
A source generator adds AcceptChanges, HasChanged, Revert, and WithProperties directly to your class:
Note: When using this attribute the Revertible instance is lazily loaded and change tracking will not begin until AcceptChanges is called. This can be done in the revertible objects constructor
using Dhazel.Revertibles;
[RevertibleObject]
public partial class Person
{
[Revertible]
public int Id { get; set; }
[Revertible]
public string? Name { get; set; }
}
var person = new Person { Id = 1, Name = "Ada" };
// AcceptChanges() runs automatically after construction by default
person.Name = "Grace";
person.HasChanged(); // true
person.Revert(); // Name restored to "Ada"
The class must be declared partial — an analyzer (REV001) flags this as a compile error if you forget. A second analyzer (REV002) warns if a [RevertibleObject] class has no [Revertible] properties, since that combination silently does nothing.
Deferring the initial snapshot
By default, the generated code snapshots pristine values the first time you call AcceptChanges, HasChanged, Revert, or WithProperties — which, left alone, happens automatically right after construction.
If your class needs additional setup before its properties are safe to snapshot (e.g. a base class that finishes initializing after your constructor runs), set AcceptPristineValues = false and call AcceptChanges() yourself once setup is complete:
[RevertibleObject(AcceptPristineValues = false)]
public partial class PersonViewModel : ObservableValidator
{
[Revertible]
public int Id { get; set; }
public PersonViewModel()
{
// ... setup that must happen before values are snapshotted ...
AcceptChanges();
}
}
Reference both packages/projects as needed:
Dhazel.Revertibles— core typesDhazel.Revertibles.Mvvm—RevertibleValidator(depends on Revertibles and CommunityToolkit.Mvvm)
Build & test
dotnet build Dhazel.Revertibles.slnx
dotnet test Dhazel.Revertibles.slnx
Releasing
Versions come from git tags via MinVer (v1.0.0 → package 1.0.0).
- Ensure
NUGET_USERis set as a GitHub Actions secret (nuget.org API key). - Push an annotated tag:
git tag -a v1.0.0 -m "v1.0.0"
git push origin v1.0.0
The Release workflow runs tests, packs, and publishes to nuget.org.
Solution layout
root/
├── Dhazel.Revertibles/ # Core library
├── Dhazel.Revertibles/Generators # Roslyn Generators
├── Dhazel.Revertibles.Mvvm/ # MVVM helpers
├── Dhazel.TestHelpers/ # Test utilities
├── Dhazel.Revertibles.Tests/
├── Dhazel.Revertibles.Generators.Tests/
├── Dhazel.Revertibles.Mvvm.Tests/
└── Dhazel.Revertibles.slnx
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CommunityToolkit.Diagnostics (>= 8.4.0)
- CommunityToolkit.Mvvm (>= 8.4.0)
- Dhazel.Revertibles (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.0 | 435 | 8/11/2026 |
| 1.0.1-alpha.0.3 | 69 | 8/11/2026 |
| 1.0.0 | 237 | 7/18/2026 |