Generated code — before / after

Aha without cloning: what NotifyGen emits for a typical ViewModel.

Before (you write)

using NotifyGen;

[Notify]
public partial class Person
{
    private string _firstName;
    private string _lastName;

    [NotifyComputed]
    public string FullName => $"{FirstName} {LastName}";

    partial void OnFirstNameChanged(string oldValue, string newValue);
}

After (generator emits — inspectable C#)

// <auto-generated/>
#nullable enable

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

partial class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    public string FirstName
    {
        get => _firstName;
        set
        {
            if (EqualityComparer<string>.Default.Equals(_firstName, value)) return;
            var oldValue = _firstName;
            OnFirstNameChanging(oldValue, value);
            _firstName = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(FullName));
            OnFirstNameChanged();
            OnFirstNameChanged(oldValue, value);
        }
    }

    public string LastName
    {
        get => _lastName;
        set
        {
            if (EqualityComparer<string>.Default.Equals(_lastName, value)) return;
            var oldValue = _lastName;
            OnLastNameChanging(oldValue, value);
            _lastName = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(FullName));
            OnLastNameChanged();
            OnLastNameChanged(oldValue, value);
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    partial void OnFirstNameChanging(string oldValue, string newValue);
    partial void OnFirstNameChanged();
    partial void OnFirstNameChanged(string oldValue, string newValue);
    partial void OnLastNameChanging(string oldValue, string newValue);
    partial void OnLastNameChanged();
    partial void OnLastNameChanged(string oldValue, string newValue);
}

Why this matters

  • No runtime package — generated C# only
  • Debuggable — set breakpoints in the partial you own; step into equality guards
  • Host reuse — if a base already implements INPC, NotifyGen calls that invoker instead of emitting a second event

Next: Migration from CommunityToolkit · Features