diff --git a/reactiveui/docs/handbook/view-models/boilerplate-code.md b/reactiveui/docs/handbook/view-models/boilerplate-code.md
index cef1dbe5..7bbb8c05 100644
--- a/reactiveui/docs/handbook/view-models/boilerplate-code.md
+++ b/reactiveui/docs/handbook/view-models/boilerplate-code.md
@@ -1,7 +1,20 @@
---
NoTitle: true
---
-If you are tired of writing boilerplate code for property change notifications, you can try either PropertyChanged.Fody or ReactiveUI.Fody. These libraries are both based on Fody - an extensible tool for weaving .NET assemblies, and they'll inject `INotifyPropertyChanged` code into properties at compile time for you. We recommend using ReactiveUI.Fody package that also handles `ObservableAsProperyHelper` properties.
+If you are tired of writing boilerplate code for property change notifications, you can try one of the following:
+- [PropertyChanged.Fody](https://github.com/Fody/PropertyChanged) or
+- [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody).
+
+These two libraries are both based on [Fody](https://github.com/Fody) - an extensible tool for weaving .NET assemblies, and they'll
+inject `INotifyPropertyChanged` code into decorated properties at compile time for you.
+
+- [ReactiveUI.SourceGenerators](https://www.nuget.org/packages/ReactiveUI.SourceGenerators/)
+
+This library is a Source Generator that generates properties and commands for you. It is a new way to generate properties and commands for ReactiveUI taking decorated fields and methods and generating the properties and ReactiveCommands for you.
+
+We recommend using [ReactiveUI.SourceGenerators](https://www.nuget.org/packages/ReactiveUI.SourceGenerators/) package that also handles `ObservableAsProperyHelper` properties and `ReactiveCommands`.
+
+# The manual way to create properties in ReactiveUI
## Read-write properties
Typically properties are declared like this:
@@ -15,15 +28,6 @@ public string Name
}
```
-With [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody/), you don't have to write boilerplate code for getters and setters of read-write properties — the package will do it automagically for you at compile time. All you have to do is annotate the property with the `[Reactive]` attribute, as shown below.
-
-```cs
-[Reactive]
-public string Name { get; set; }
-```
-
-> **Note** `ReactiveUI.Fody` currently doesn't support inline auto property initializers in generic types. It works fine with non-generic types. But if you are working on a generic type, don't attempt to write code like `public string Name { get; set; } = "Name";`, this won't work as you might expect and will likely throw a very weird exception. To workaround this limitation, move your property initialization code to the constructor of your view model class. We know about this limitation and [have a tracking issue for this](https://github.com/reactiveui/ReactiveUI/issues/2416).
-
## ObservableAsPropertyHelper properties
Similarly, to declare output properties, the code looks like this:
@@ -41,6 +45,216 @@ _firstName = firstNameObservable
.ToProperty(this, x => x.FirstName);
```
+# Using ReativeUI.SourceGenerators
+
+With [ReactiveUI.SourceGenerators](https://www.nuget.org/packages/ReactiveUI.SourceGenerators/).
+
+These Source Generators were designed to work in full with ReactiveUI V19.5.31 and newer supporting all features, currently:
+- `[Reactive]`
+- `[ObservableAsProperty]`
+- `[ReactiveCommand]`
+
+Versions older than V19.5.31 to this:
+- `[Reactive]` fully supported,
+- `[ObservableAsProperty]` fully supported,
+- `[ReactiveCommand]` all supported except Cancellation Token asnyc methods.
+
+The Source Generators are not a direct replacement for [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody/), but they can be used together.
+You can contine to use ReactiveUI.Fody an migrate to ReactiveUI.SourceGenerators at your own pace.
+
+As fody operates at the IL level, it can be used to generate properties that directly replace the code you specified in the Property templates for `[Reactive]` and `[ObservableAsProperty]` properties.
+Source Generators add to your code instead of replacing it, so you we use fields and methods to generate the properties and commands.
+
+The `[Reactive]` and `[ObservableAsProperty]` Attributes are applied to fields, and the Source Generator will generate the properties for you.
+`[Reactive]` will generate a property with a backing field and the RaiseAndSetIfChanged method. You can provide initialisers for the field.
+`[ObservableAsProperty]` will generate a property with a ObservableAsPropertyHelper backing field. Any initialisers will be ignored.
+
+The `[ReactiveCommand]` Attribute is applied to methods, and the Source Generator will generate a ReactiveCommand property for you.
+The method can be one of the following
+- a void method,
+- a method with a return value,
+- a method with a return value and a parameter,
+- a method with a return value of Task.
+- a method with a return value of Task and a parameter,
+- a method with a return value of Task and a CancellationToken,
+- a method with a return value of Task and a parameter and a CancellationToken,
+- a method with a return value of Task of T.
+- a method with a return value of Task of T and a parameter,
+- a method with a return value of Task of T and a CancellationToken,
+- a method with a return value of Task of T and a parameter and a CancellationToken,
+- a method with a return value of IObservable,
+- a method with a return value of IObservable and a parameter.
+
+
+## Usage Reactive property `[Reactive]`
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass : ReactiveObject
+{
+ [Reactive]
+ private string _myProperty;
+}
+```
+
+## Usage ObservableAsPropertyHelper `[ObservableAsProperty]`
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass : ReactiveObject
+{
+ [ObservableAsProperty]
+ private string _firstName;
+
+ private IObservable _firstNameObservable;
+
+ public MyReactiveClass()
+ {
+ // TODO: Replace with your own observable
+ _firstNameObservable = Observable.Return("John");
+ _firstNameHelper = _firstNameObservable
+ .ToProperty(this, x => x.FirstName);
+ }
+
+ public IObservable FirstNameObservable => _firstNameObservable;
+}
+```
+
+## Usage ReactiveCommand `[ReactiveCommand]`
+
+### Usage ReactiveCommand without parameter
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private void Execute() { }
+}
+```
+
+### Usage ReactiveCommand with parameter
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private void Execute(string parameter) { }
+}
+```
+
+### Usage ReactiveCommand with parameter and return value
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private string Execute(string parameter) => parameter;
+}
+```
+
+### Usage ReactiveCommand with parameter and async return value
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private async Task Execute(string parameter) => await Task.FromResult(parameter);
+}
+```
+
+### Usage ReactiveCommand with IObservable return value
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private IObservable Execute(string parameter) => Observable.Return(parameter);
+}
+```
+
+### Usage ReactiveCommand with CancellationToken
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private async Task Execute(CancellationToken token) => await Task.Delay(1000, token);
+}
+```
+
+### Usage ReactiveCommand with CancellationToken and parameter
+```csharp
+using ReactiveUI.SourceGenerators;
+
+public partial class MyReactiveClass
+{
+ public MyReactiveClass()
+ {
+ InitializeCommands();
+ }
+
+ [ReactiveCommand]
+ private async Task Execute(string parameter, CancellationToken token)
+ {
+ await Task.Delay(1000, token);
+ return parameter;
+ }
+}
+```
+
+
+# Using ReactiveUI.Fody
+
+With [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody/), you don't have to write boilerplate code for getters and setters of read-write properties — the package will do it automagically for you at compile time.
+All you have to do is annotate the property with the `[Reactive]` attribute, as shown below.
+
+## Read-write properties
+
+```cs
+[Reactive]
+public string Name { get; set; }
+```
+
+> **Note** `ReactiveUI.Fody` currently doesn't support inline auto property initializers in generic types. It works fine with non-generic types. But if you are working on a generic type, don't attempt to write code like `public string Name { get; set; } = "Name";`, this won't work as you might expect and will likely throw a very weird exception. To workaround this limitation, move your property initialization code to the constructor of your view model class. We know about this limitation and [have a tracking issue for this](https://github.com/reactiveui/ReactiveUI/issues/2416).
+
+## ObservableAsPropertyHelper properties
+
With ReactiveUI.Fody, you can simply declare a read-only property using the `[ObservableAsProperty]` attribute, using either option of the two options shown below. One option is to annotate the getter of the property:
```cs