Vetuviem.SourceGenerator 0.14.4

dotnet add package Vetuviem.SourceGenerator --version 0.14.4
                    
NuGet\Install-Package Vetuviem.SourceGenerator -Version 0.14.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Vetuviem.SourceGenerator" Version="0.14.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Vetuviem.SourceGenerator" Version="0.14.4" />
                    
Directory.Packages.props
<PackageReference Include="Vetuviem.SourceGenerator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Vetuviem.SourceGenerator --version 0.14.4
                    
#r "nuget: Vetuviem.SourceGenerator, 0.14.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Vetuviem.SourceGenerator@0.14.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Vetuviem.SourceGenerator&version=0.14.4
                    
Install as a Cake Addin
#tool nuget:?package=Vetuviem.SourceGenerator&version=0.14.4
                    
Install as a Cake Tool

Vetuviem

Vetuviem is a toolkit to support View to View Model binding (MVVM → V2VM → Ve-Tu-Viem) aimed at offering a structure to get more re-usability out of ReactiveUI.

Mission Statement

  • To give a mechanism to reduce the amount of boiler plate code being produced, by allowing some of the ReactiveUI specific logic to be hidden away
  • Allow the developer to think along the lines of standard behaviours for controls by offering a way to produce re-usable behaviours through a class and\or function design pattern
  • Allow the developer to focus on what matters on the ViewModel
  • Reduce the cognitive load by
    • Removing the risk of misusing 1 way or 2 way binding
    • Remove the need for the user to think about having to cater for Bind vs BindCommand
  • Offer a structure that allows for more work to be done potentially with Source Generators to reduce reflection and improve the build time developer experience.

Current Status

This is currently a proof of concept alpha. For understanding of the design reasoning please see https://www.dpvreony.com/articles/designing-vetuviem/

Nuget Packages

Purpose Package NuGet
Command Line Generation Coming soon Coming Soon
Visual Studio Integration Vetuviem.SourceGenerator VetuviemSourceGeneratorBadge
Core Functionality Vetuviem.Core VetuviemCoreBadge

Getting started

Install the desired package

TODO

Add workaround for Windows based builds

On CI runners you can occasionally find that the Source generators fail to load with soemthing along the lines of ErrorCode: ReferencesNewerCompiler, ReferencedCompilerVersion: 5.0.0.0. NOTE: different .NET SDK or MSBuild versions are inconsistent with the error message, you may sometimes see it prefixed with ADR0001 or CS9057, other times it has no prefix.

This is currently (as of 2026-01) an issue with Github Actions where Visual Studio 2022 is on the Agent. This forces MSBuild to use the desired version rather than the one built into Visual Studio and MSBuild.

Place the following in a Dir.Build.Props file or the relevant C# project file(s).

  
  <PropertyGroup>
    
    <UseSharedCompilation>false</UseSharedCompilation>
  </PropertyGroup>
  
  <ItemGroup>
    
    <PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="5.0.0" Condition="'$(MSBuildRuntimeType)' != 'Core'">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

An example

Currently to write binding logic in the codebehind you have to write something similar to this for a single control

// Traditional ReactiveUI binding approach
this.WhenActivated(disposables =>
{
    this.Bind(ViewModel, vm => vm.Forename, v => v.Forename.Text)
        .DisposeWith(disposables);
    this.OneWayBind(ViewModel, vm => vm.ForenameLengthRemaining, v => v.ForenameLengthRemaining.Content)
        .DisposeWith(disposables);
    this.OneWayBind(ViewModel, vm => vm.ForenameLengthRemaining, v => v.ForenameLengthRemaining.Foreground, 
        lengthRemaining => GetBrushForLengthRemaining(lengthRemaining))
        .DisposeWith(disposables);
});

But what if you have a way to simplify logic and offer a way to even make it reusable without all the boilerplate leg work?

// Vetuviem approach using ViewBindingModels
public sealed class QuestionnaireViewBindingModels : AbstractEnableViewToViewModelBindings<QuestionnaireView, QuestionnaireViewModel>
{
    protected override IEnumerable<IControlBindingModel<QuestionnaireView, QuestionnaireViewModel>> GetBindings()
    {
        yield return new TextBoxControlBindingModel<QuestionnaireView, QuestionnaireViewModel>(vw => vw.Forename)
        {
            Text = new TwoWayBinding<QuestionnaireViewModel, string>(vm => vm.Forename),
        };
        
        yield return new LabelControlBindingModel<QuestionnaireView, QuestionnaireViewModel>(vw => vw.ForenameLengthRemaining)
        {
            Content = new OneWayBindingOnOneOrTwoWayBind<QuestionnaireViewModel, object>(vm => vm.ForenameLengthRemaining, o => o?.ToString() ?? string.Empty),
            Foreground = new OneWayBindingWithConversionOnOneOrTwoWayBind<QuestionnaireViewModel, Brush, int>(vm => vm.ForenameLengthRemaining, lengthRemaining => GetBrushForLengthRemaining(lengthRemaining))
        };
    }
}

Configuration

Vetuviem source generators can be configured through MSBuild properties in your project file (.csproj). Add these properties to a <PropertyGroup> section to customize code generation behavior.

Available Properties

Property Description Default Value
Vetuviem_Root_Namespace Override the root namespace for generated code (Project's root namespace)
Vetuviem_Make_Classes_Public Make generated classes public instead of internal false
Vetuviem_Assemblies Comma-separated list of assemblies to scan for controls (Platform-specific defaults)
Vetuviem_Assembly_Mode How to use custom assemblies: Replace or Extend Replace
Vetuviem_Base_Namespace Base namespace when using custom assemblies (none)
Vetuviem_Include_Obsolete_Items Include properties marked with ObsoleteAttribute false
Vetuviem_Allow_Experimental_Properties Include properties marked with ExperimentalAttribute false
Vetuviem_Logging_Implementation_Mode Logging implementation: None or SplatViaServiceLocator SplatViaServiceLocator

Property Details

Vetuviem_Root_Namespace

Override the default root namespace for generated code. This is useful when you want generated binding models to reside in a specific namespace.

Example:

<PropertyGroup>
  <Vetuviem_Root_Namespace>MyApp.Generated</Vetuviem_Root_Namespace>
</PropertyGroup>
Vetuviem_Make_Classes_Public

Controls the visibility of generated binding model classes. By default, classes are generated as internal. Set this to true to make them public.

Example:

<PropertyGroup>
  <Vetuviem_Make_Classes_Public>true</Vetuviem_Make_Classes_Public>
</PropertyGroup>
Vetuviem_Assemblies

Specify a comma-separated list of assemblies to scan for control types. Use in conjunction with Vetuviem_Assembly_Mode to either replace or extend the default platform assemblies.

Example:

<PropertyGroup>
  <Vetuviem_Assemblies>CustomControls.dll,ThirdPartyControls.dll</Vetuviem_Assemblies>
</PropertyGroup>
Vetuviem_Assembly_Mode

Determines how the assemblies specified in Vetuviem_Assemblies are used:

  • Replace (default): Replace platform defaults with your custom assemblies
  • Extend: Add custom assemblies in addition to platform defaults

Example:

<PropertyGroup>
  <Vetuviem_Assembly_Mode>Extend</Vetuviem_Assembly_Mode>
</PropertyGroup>
Vetuviem_Base_Namespace

Used with custom assemblies to specify a base namespace. This allows third parties to use the generator and produce custom namespaces that inherit from the root or use a custom namespace.

Example:

<PropertyGroup>
  <Vetuviem_Base_Namespace>MyCompany.Controls</Vetuviem_Base_Namespace>
</PropertyGroup>
Vetuviem_Include_Obsolete_Items

Controls whether properties marked with ObsoleteAttribute are included in code generation. By default, obsolete items are excluded.

Example:

<PropertyGroup>
  <Vetuviem_Include_Obsolete_Items>true</Vetuviem_Include_Obsolete_Items>
</PropertyGroup>
Vetuviem_Allow_Experimental_Properties

Starting with .NET 10, properties can be marked with ExperimentalAttribute to indicate they are experimental APIs. This property controls how these are handled:

When false or not set (default):

  • Properties marked with ExperimentalAttribute are excluded from code generation
  • No warnings are generated
  • Experimental properties are silently skipped
  • Ensures backward compatibility

When true:

  • Properties marked with ExperimentalAttribute are included in code generation
  • A SuppressMessage attribute is automatically added to suppress experimental warnings
  • The diagnostic ID from the ExperimentalAttribute is extracted and used in the suppression

Example:

<PropertyGroup>
  <Vetuviem_Allow_Experimental_Properties>true</Vetuviem_Allow_Experimental_Properties>
</PropertyGroup>

Example Control Property:

[Experimental("WFDEV001")]
public ThemeMode ThemeMode { get; set; }

Generated Binding Property (when enabled):

[SuppressMessage("Usage", "WFDEV001")]
public IOneOrTwoWayBind<TViewModel, ThemeMode>? ThemeMode { get; init; }

Notes:

  • The diagnostic ID is read from the first constructor argument of ExperimentalAttribute
  • Only properties with public accessibility are considered for generation (standard behavior)
Vetuviem_Logging_Implementation_Mode

Controls the logging implementation generated in binding code:

  • None: No logging implementation
  • SplatViaServiceLocator (default): Uses Splat logging via service locator

Example:

<PropertyGroup>
  <Vetuviem_Logging_Implementation_Mode>None</Vetuviem_Logging_Implementation_Mode>
</PropertyGroup>

Support

For support, please:

  • Check the design article for understanding the design reasoning
  • Report bugs or request features via GitHub Issues
  • Ask questions in GitHub Discussions
  • Review the sample applications in the src directory for practical examples

Contribute

Contributions are welcome! Please:

  • Read the Code of Conduct
  • Fork the repository and create a feature branch
  • Write tests for your changes
  • Ensure all tests pass and code follows the existing style
  • Submit a Pull Request with a clear description of your changes

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.14.4 2,318 3/5/2026
0.14.1 164 3/2/2026
0.13.7 837 2/23/2026
0.13.1 187 1/15/2026
0.12.19 172 1/1/2026
0.12.16 190 12/12/2025
0.12.15 497 12/10/2025
0.11.14 475 9/2/2025
0.11.2 405 6/28/2025
0.11.1 191 6/27/2025
0.10.102 216 6/21/2025
0.10.101 173 6/20/2025
0.10.100 173 6/20/2025
0.10.88 320 5/17/2025
0.10.67 665 1/18/2025
0.10.18 862 6/14/2024
0.10.17 242 6/14/2024
0.10.15 241 6/12/2024
0.10.12 244 6/9/2024
0.10.11 252 6/5/2024
Loading failed