### BenchmarkDotNet Configuration and Results Source: https://github.com/nventive/chinook.dynamicmvvm/wiki/Benchmarks-1.2.2 This snippet details the BenchmarkDotNet setup and the resulting performance metrics for the Chinook.DynamicMVVM project. It includes environment information, job configurations, and detailed performance data for various methods, such as ViewModel creation, property access, and disposal. ```text BenchmarkDotNet v0.13.11, Windows 10 (10.0.19045.3324/22H2/2022Update) Intel Core i7-10850H CPU 2.70GHz, 1 CPU, 12 logical and 6 physical cores .NET SDK 7.0.304 [Host] : .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2 DefaultJob : .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2 Job-SMXNIU : .NET 7.0.7 (7.0.723.27404), X64 RyuJIT AVX2 | Method | Job | InvocationCount | UnrollFactor | Mean | Error | StdDev | Median | Gen0 | Gen1 | Allocated | |------------------------------------ |----------- |---------------- |------------- |----------:|----------:|----------:|----------:|-------:|-------:|----------:| | CreateViewModel | DefaultJob | Default | 16 | 2.278 μs | 0.0428 μs | 0.0856 μs | 2.284 μs | 0.3204 | 0.3166 | 2023 B | | ReadProperty_Unresolved | Job-SMXNIU | 1 | 1 | 2.754 μs | 0.0585 μs | 0.1630 μs | 2.800 μs | - | - | 1032 B | | ReadProperty_Resolved | Job-SMXNIU | 1 | 1 | 1.409 μs | 0.0322 μs | 0.0902 μs | 1.400 μs | - | - | 896 B | | SetProperty_Unresolved | Job-SMXNIU | 1 | 1 | 19.147 μs | 0.2796 μs | 0.2615 μs | 19.100 μs | - | - | 3016 B | | SetProperty_Resolved | Job-SMXNIU | 1 | 1 | 1.957 μs | 0.0428 μs | 0.1074 μs | 2.000 μs | - | - | 832 B | | DisposeViewModel | Job-SMXNIU | 1 | 1 | 2.954 μs | 0.0614 μs | 0.0881 μs | 2.950 μs | - | - | 776 B | | SetProperty_Unresolved_WithListener | Job-SMXNIU | 1 | 1 | 21.014 μs | 0.4206 μs | 1.1227 μs | 21.000 μs | - | - | 3256 B | | SetProperty_Resolved_WithListener | Job-SMXNIU | 1 | 1 | 3.031 μs | 0.0640 μs | 0.1051 μs | 3.000 μs | - | - | 1088 B | | DisposeViewModel_WithListener | Job-SMXNIU | 1 | 1 | 2.932 μs | 0.0722 μs | 0.2118 μs | 3.000 μs | - | - | 776 B | ``` -------------------------------- ### Create Basic ViewModel with DynamicMvvm Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Demonstrates the creation of a basic ViewModel using `ViewModelBase` from the Chinook.DynamicMvvm library. It shows how to declare properties and commands using the `Get` and `GetCommand` methods for simplified MVVM implementation. ```csharp using Chinook.DynamicMvvm; // (...) public class MainPageViewModel : ViewModelBase { public string Content { get => this.Get(initialValue: string.Empty); set => this.Set(value); } public IDynamicCommand Submit => this.GetCommand(() => { Result = Content; }); public string Result { get => this.Get(initialValue: string.Empty); private set => this.Set(value); } } ``` -------------------------------- ### Creating a Custom Delegating Command Strategy Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Provides an example of creating a custom delegating command strategy by inheriting from DelegatingCommandStrategy. This allows for custom logic in CanExecute and Execute methods, and shows how to create an extension method to easily apply the custom strategy. ```csharp public class MyCustomCommandStrategy : DelegatingCommandStrategy { public MyCustomCommandStrategy(IDynamicCommandStrategy innerStrategy) : base(innerStrategy) { } public override bool CanExecute(object parameter, IDynamicCommand command) { // Implement your custom logic here. return base.CanExecute(parameter, command); } public override async Task Execute(CancellationToken ct, object parameter, IDynamicCommand command) { // Implement your custom logic here. base.Execute(ct, parameter, command); } } public static class MyCustomCommandStrategyExtensions { public static IDynamicCommandStrategy WithMyCustomStrategy(this IDynamicCommandStrategy strategy) => new MyCustomCommandStrategy(strategy); } // This will decorate the strategy with your custom one. var myCommandWithMyCustomStrategy = myCommandStrategy.WithMyCustomStrategy(); ``` -------------------------------- ### Register Validators in Service Provider in C# Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Provides an example of how to register all validators from a specific assembly with the service provider, typically done during application startup. ```csharp serviceCollection.AddValidatorsFromAssemblyContaining(typeof(App), ServiceLifetime.Singleton) ``` -------------------------------- ### Get and Observe DynamicProperty Value (C#) Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Property/IDynamicProperty.md Illustrates using the 'GetAndObserve' extension method, which first emits the current value and then continues to emit subsequent changes to the DynamicProperty's value. ```csharp myProperty.GetAndObserve().Subscribe(value => { // This will be called a first time with the initial value of the property. // It will then be called everytime the value of the property changes. }); ``` -------------------------------- ### Inheriting from ViewModelBase Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/ViewModel/IViewModel.md Demonstrates the basic structure of creating a custom ViewModel by inheriting from the provided ViewModelBase class. This is the most common starting point for creating ViewModels in the Chinook Dynamic MVVM framework. ```csharp public class MyViewModel : ViewModelBase { } ``` -------------------------------- ### Integrate Dispatcher for UI Thread Updates (UWP/Uno Legacy) Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Provides an example of integrating a dispatcher for UI thread updates in UWP or Uno.UI (legacy) applications using `Chinook.DynamicMvvm`. It shows initializing `MainPageViewModel` with a `CoreDispatcherDispatcher` for proper `INotifyPropertyChanged` event handling on the main thread. ```csharp public MainPage() { this.InitializeComponent(); DataContext = new MainPageViewModel() { Dispatcher = new CoreDispatcherDispatcher(this) }; } ``` -------------------------------- ### Using Dynamic Properties in ViewModel Constructor Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/ViewModel/IViewModel.md Provides an example of how to access the values of one-way and set the values of two-way dynamic properties within the ViewModel's constructor. This demonstrates the immediate usability of these properties after creation. ```csharp public MyViewModel() { // This will get the value of the IDynamicProperty named MyOneWayProperty var myValue = MyOneWayProperty; // This will set the value of the IDynamicProperty named MyTwoWayProperty MyTwoWayProperty = 20; } ``` -------------------------------- ### Subscribe to DynamicCommand Execution Changes Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Shows how to subscribe to the IsExecutingChanged event of a DynamicCommand to be notified when the command starts or stops executing. An event handler method is provided. ```csharp void OnIsExecutingChanged(object sender, EventArgs e) { } myCommand.IsExecutingChanged += OnIsExecutingChanged; ``` -------------------------------- ### Get and Set DynamicProperty Value (C#) Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Property/IDynamicProperty.md Shows how to access the current value of a DynamicProperty using its 'Value' property and how to update it, which triggers notifications to subscribers. ```csharp var myValue = myProperty.Value; myProperty.Value = 30; ``` -------------------------------- ### Observe Property Value with IObservable Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Shows how to use the Observe() and GetAndObserve() extension methods on an IDynamicProperty to get an IObservable that emits values when the property changes. This integrates with System.Reactive. ```csharp IObservable observable; observable = contentProperty.Observe(); // Gets an IObservable that yields when the value changes. observable = contentProperty.GetAndObserve(); // Gets an IObservable that yields when the value changes and starts with the current value. ``` -------------------------------- ### Customize Command Declaration Behavior Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md This C# example shows how to customize the behavior of a specific command, `Submit`, at the declaration level. It uses a builder to apply the `SkipWhileExecuting` strategy, which prevents the command from executing if it's already in progress. This configuration is additive to any factory-level settings. ```csharp public IDynamicCommand Submit => this.GetCommand(() => { Result = Content; }, builder => builder .SkipWhileExecuting() ); ``` -------------------------------- ### Create and Execute a Basic DynamicCommand Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Demonstrates creating a DynamicCommand with a name and an action strategy, then executing it. The associated action method is called upon execution. ```csharp var myCommandStrategy = new ActionCommandStrategy(ExecuteCommand); var myCommand = new DynamicCommand("MyCommand", myCommandStrategy); void ExecuteCommand() { // Command execution logic here. } await myCommand.Execute(); ``` -------------------------------- ### Configure IDynamicCommand Locally with Builder Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Shows how to apply local configurations, such as adding logging, to an IDynamicCommand using extension methods on the IDynamicCommandBuilder. ```csharp var myFactory = new DynamicCommandBuilderFactory(); var myBuilder = myFactory.CreateFromAction("MyCommand", ExecuteCommand) .WithLogs(); var myCommand = myBuilder.Build(); private void ExecuteCommand() { } ``` -------------------------------- ### Create IDynamicCommand with Builder Factory Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Demonstrates the basic usage of IDynamicCommandBuilderFactory and IDynamicCommandBuilder to create a new IDynamicCommand from an action. ```csharp var myFactory = new DynamicCommandBuilderFactory(); var myBuilder = myFactory.CreateFromAction("MyCommand", ExecuteCommand); var myCommand = myBuilder.Build(); private void ExecuteCommand() { } ``` -------------------------------- ### Configure ServiceProvider with DynamicMvvm Factories Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Illustrates how to configure a `System.IServiceProvider` using `Microsoft.Extensions.DependencyInjection` and `Microsoft.Extensions.Hosting`. It registers the necessary `IDynamicCommandBuilderFactory` and `IDynamicPropertyFactory` implementations required by Chinook.DynamicMvvm. ```csharp var serviceProvider = new HostBuilder() .ConfigureServices(serviceCollection => serviceCollection .AddSingleton() .AddSingleton() ) .Build() .Services; ``` -------------------------------- ### Create Commands from Action Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Illustrates creating IDynamicCommand instances from Action delegates for commands without parameters, and Action delegates for commands that accept a parameter. These are created using GetCommand(). ```csharp public IDynamicCommand SayHi => this.GetCommand(() => { Console.WriteLine("Hi"); }); public IDynamicCommand SaySomething => this.GetCommand(parameter => { Console.WriteLine(parameter); }); ``` -------------------------------- ### Apply Default Configuration to Command Factory Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/Command/IDynamicCommand.md Illustrates how to set a default configuration for all commands created by an IDynamicCommandBuilderFactory, including executing on a background thread, catching errors, and adding logs. ```csharp var myFactory = new DynamicCommandBuilderFactory(c => c .ExecuteOnBackgroundThread() .CatchErrors(HandleCommandError) .WithLogs() )); var myBuilder = myFactory.CreateFromAction("MyCommand", ExecuteCommand); var myCommand = myBuilder.Build(); private void ExecuteCommand() { } ``` -------------------------------- ### Configuring DynamicPropertyFactory Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/ViewModel/IViewModel.md Illustrates how to customize the creation of dynamic properties by registering a custom `IDynamicPropertyFactory` with the service collection. This allows for advanced property creation logic. ```csharp private void ConfigureProperties(IServiceCollection services) { services.AddSingleton(); } ``` -------------------------------- ### Create Commands from Async Methods Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Demonstrates creating IDynamicCommand instances from asynchronous methods using GetCommandFromTask(). This includes handling Func for parameterless async commands and Func for async commands with parameters, utilizing CancellationToken for cancellation. ```csharp public IDynamicCommand WaitASecond => this.GetCommandFromTask(async ct => { await Task.Delay(1000, ct); }); public IDynamicCommand Wait => this.GetCommandFromTask(async (ct, parameter) => { await Task.Delay(TimeSpan.FromSeconds(parameter), ct); }); ``` -------------------------------- ### Creating Dynamic Properties with Initial Values Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/src/DynamicMvvm.Abstractions/ViewModel/IViewModel.md Demonstrates various ways to create dynamic properties with specified initial values. This includes setting a default value, providing a literal value, and initializing from a Task or an Observable. ```csharp public int MyProperty => this.Get(); // This will create and attach a new IDynamicProperty named "MyPropertyWithInitialValue" // to your IViewModel. It's initial value will be 10. public int MyPropertyWithInitialValue => this.Get(10)); // This will create and attach a new IDynamicProperty named "MyPropertyFromTask" // to your IViewModel. It's initial value will be 10 and will be updated to 20 // once MyTask completes. public int MyPropertyFromTask => this.GetFromTask(MyTask, initialValue: 10); private Task MyTask(CancellationToken ct) => Task.FromResult(20); // This will create and attach a new IDynamicProperty named "MyPropertyFromObservable" // to your IViewModel. It's initial value will be 10 and will be updated to 20 // once MyObservable pushes a new value. public int MyPropertyFromObservable => this.GetFromObservable(MyObservable, initialValue: 10); private IObservable MyObservable => Observable.Return(20); ``` -------------------------------- ### Basic MainPage.xaml Binding Source: https://github.com/nventive/chinook.dynamicmvvm/blob/main/README.md Provides a simple XAML structure for `MainPage` that demonstrates data binding to the `MainPageViewModel`. It includes a `TextBox` for input, a `Button` to trigger a command, and a `TextBlock` to display results, all bound to ViewModel properties. ```xml