MvvmGen 1.1.0 and the New Special Edition: PURE CODE GENERATION – No Runtime Dependency For Your Project!
In the last blog post I introduced you to MvvmGen, the new MVVM library built with a strong focus on C# Source Generators. Some of you asked in the comments of the blog post and also per email if also the library could be generated, so that there is no runtime dependency.
Today, I’m happy to announce that this is now possible. Check out the requested special edition on NuGet: MvvmGen.PureCodeGeneration. This edition generates everything for you, not only the ViewModels, but also the full library. That means, there is no runtime dependency for your application. Let’s look at this edition in this blog post, and let me also show you what’s new in version 1.1.0.
Before we look at the details, let’s look at the structure of the normal MvvmGen NuGet package.
The Normal MvvmGen NuGet Package
When you reference the MvvmGen NuGet package in your project, you’ll get two things:
a) A development dependency: The ViewModelGenerator
, which generates your ViewModels
b) A runtime dependency: The MvvmGen.dll
The MvvmGen.dll contains MvvmGen‘s ViewModelBase
class, the EventAggregator
, the DelegateCommand
, and all the attributes like ViewModel
and Property
that you use to decorate your ViewModel classes. When you look at the following screenshot, you can see in the Solution Explorer the ViewModelGenerator
and also the MvvmGen.dll.
When you build your app, you’ll see the MvvmGen.dll in the output folder, as that assembly is required to run your application:
Now let’s look at pure code generation with MvvmGen.PureCodeGeneration.
The MvvmGen.PureCodeGeneration NuGet package
When you search on NuGet for MvvmGen, you’ll find two packages: MvvmGen and MvvmGen.PureCodeGeneration.
You don’t use both packages at the same time, you use either MvvmGen or MvvmGen.PureCodeGeneration. Both packages have exactly the same functionality for you as a developer, but the second one does not only generate your ViewModels, but also the full library code. That means there is no MvvmGen.dll and so also no runtime dependency. Let me quote the package description here:
MvvmGen.PureCodeGeneration is a lightweight, modern MVVM library for XAML applications. This package is a special version of the MvvmGen NuGet package. It has the same functionality, but it generates not only your ViewModels, but also the full MvvmGen library. This means that you have zero runtime dependencies with this package. As the package name says, it’s pure code generation.
Package description of MvvmGen.PureCodeGeneration
Now, when you reference that MvvmGen.PureCodeGeneration package in your application, you’ll see the following in the Solution Explorer. As you can see, the whole MvvmGen library is generated for you, and you actually compile that full library code as a part of your project. You can also look at the library code by double-clicking on a file. But as it is generated, you’re not allowed to change it.
You can also see in the screenshot above that this MvvmGen.PureCodeGeneration NuGet package has a ViewModelAndLibraryGenerator
. This is exactly the same generator as the ViewModelGenerator
that comes with the MvvmGen NuGet package. The only difference is that this generator also generates the library code for you, so that you have zero runtime dependencies.
Which Package Should You Use
As both packages have exactly the same APIs, you can easily swap them at any time. They are actually built from exactly the same sources. So, the generated MvvmGen*.g.cs files that you see in the screenshot above and that you get with the MvvmGen.PureCodeGeneration NuGet package are exactly the C# files that are compiled into the MvvmGen.dll of the MvvmGen NuGet package.
Right now, it looks like Visual Studio 2019 has a very little bit better coding support for the MvvmGen NuGet package with the MvvmGen.dll. For example, if you create a ViewModel
attribute, Visual Studio suggest you to add a using
directive for the MvvmGen
namespace. With the MvvmGen.PureCodeGeneration NuGet package, that suggestion does not happen, and you have to manually add the using
directive for the MvvmGen
namespace. That’s the only difference I noticed, and I guess that one could probably get fixed by Visual Studio in the future.
One thing to keep in mind is that the MvvmGen NuGet package gives you a compiled .NET Standard 2.0 library that you can use in a project that does not target C# 9.0. If you use the MvvmGen.PureCodeGeneration NuGet package, you might have to use the latest C# version, as you’re also the dev who compiles the library code.
What Changed From Version 1.0.0 to Version 1.1.0?
Version 1.1.0 contains a few optimizations and a new PropertyInvalidate
attribute that you can use on read-only properties. You asked already for it, I think it makes sense, now it’s here. Let me show you how it works. Let’s say you create a FullName
property like in the ViewModel below.
[ViewModel]
public partial class EmployeeViewModel
{
[Property] private string _firstName;
[Property] private bool _lastName;
public string FullName => $"{FirstName} {LastName}";
}
That FullName
property depends on the generated properties FirstName
and LastName
. This means, the PropertyChanged
event should be raised for the FullName
property when either the FirstName
property or the LastName
property changes. But right now, when you look at the generated ViewModel in the code snippet below, you can see that this does not happen in the setters of the properties FirstName
and LastName
:
partial class EmployeeViewModel : ViewModelBase
{
public EmployeeViewModel()
{
this.OnInitialize();
}
partial void OnInitialize();
public string FirstName
{
get => _firstName;
set
{
if (_firstName != value)
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
}
public bool LastName
{
get => _lastName;
set
{
if (_lastName != value)
{
_lastName = value;
OnPropertyChanged("LastName");
}
}
}
}
To tell MvvmGen’s ViewModelGenerator
that your property depends on other properties, you use the PropertyInvalidate
attribute like you see it below:
[ViewModel]
public partial class EmployeeViewModel
{
[Property] private string _firstName;
[Property] private bool _lastName;
[PropertyInvalidate(nameof(FirstName))]
[PropertyInvalidate(nameof(LastName))]
public string FullName => $"{FirstName} {LastName}";
}
Instead of using two separate PropertyInvalidate
attributes, you can also use a single attribute, if you prefer this:
[ViewModel]
public partial class EmployeeViewModel
{
[Property] private string _firstName;
[Property] private bool _lastName;
[PropertyInvalidate(nameof(FirstName), nameof(LastName))]
public string FullName => $"{FirstName} {LastName}";
}
Now MvvmGen generates the following partial class. Note how the OnPropertyChanged
method for the FullName
property is called in the setters of the properties FirstName
and LastName
, so that the PropertyChanged
event is raised.
partial class EmployeeViewModel : ViewModelBase
{
public EmployeeViewModel()
{
this.OnInitialize();
}
partial void OnInitialize();
public string FirstName
{
get => _firstName;
set
{
if (_firstName != value)
{
_firstName = value;
OnPropertyChanged("FirstName");
OnPropertyChanged("FullName");
}
}
}
public bool LastName
{
get => _lastName;
set
{
if (_lastName != value)
{
_lastName = value;
OnPropertyChanged("LastName");
OnPropertyChanged("FullName");
}
}
}
}
What’s Next? => MvvmGen Goes Open Source!
As mentioned, MvvmGen will be open sourced in May 2021. I’m working on a first draft of the docs. I plan to open source it the next weekend. So, stay tuned.
Thank you for all your support!
Thomas
Leave a Reply