Skip to main content

Monify by Paul Martin

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: Monify

Monify, a .NET Roslyn source generator, automates the creation of strongly-typed wrappers around single values, improving semantic clarity, type safety, and maintainability.

Author: Paul Martin

NuGet: https://www.nuget.org/packages/Monify/

You can find more details at https://github.com/MooVC/monify

Source: https://github.com/MooVC/monify

Author

note

Paul Martin Alt text

Original Readme

note

Monify NuGet GitHub

Monify, a .NET Roslyn source generator, automates the creation of strongly-typed wrappers around single values, improving semantic clarity, type safety, and maintainability.

Requirements

  • C# v2.0 or later.
  • Visual Studio 2022 v17.4 or later, or any compatible IDE that supports Roslyn source generators.

Installation

To install Monify, use the following command in your package manager console:

install-package Monify

Usage

Monify turns a class, record, or struct into a strongly typed wrapper around a single value. To opt in, annotate a partial type with the Monify attribute and specify the encapsulated value type.

using Monify;

[Monify<int>]
public partial struct Age;

For language versions earlier than C# 11:

using Monify;

[Monify(Type = typeof(int))]
public partial struct Age;

Generated Members

When applied, Monify generates the boilerplate needed for a lightweight value object:

  • A private readonly field _value that stores the encapsulated value.
  • A constructor accepting the underlying value: Age(int value).
  • Implicit conversion operators to and from the encapsulated type.
  • Implementations of IEquatable<Age> and IEquatable<int>.
  • Equality (==) and inequality (!=) operators for comparing with other instances or with the underlying value.
  • Overrides of Equals(object), GetHashCode(), and ToString().

Example

Age age = 42;       // implicit conversion from int
int value = age; // implicit conversion to int

if (age == value)
{
// comparisons work with both Age and int
}

Classes annotated with Monify are sealed automatically to preserve immutability. Types must be partial and cannot declare additional state; the included analyzers will warn when these guidelines are not followed.

Nested wrappers and circular guards

Monify also follows chains of nested wrappers and automatically emits the necessary implicit conversions so the outermost wrapper can convert directly to and from the innermost value type. For example, if Money wraps Amount and Amount wraps decimal, conversions will be generated for every hop, allowing callers to cast Money to decimal (and vice versa) without manual glue code.

To keep the generator safe, conversion discovery halts as soon as a type repeats in the chain. This prevents circular relationships (e.g. Outer wrapping Inner while Inner wraps Outer) from producing infinite loops or ambiguous operators while still supporting arbitrarily deep, non-circular nesting.

Analyzers

Monify includes several analyzers to assist engineers with its usage. These are:

Rule IDCategorySeverityNotes
MONFY01UsageWarningType is not compatible with Monify
MONFY02UsageWarningType is not Partial
MONFY03DesignErrorType captures State
MONFY04DesignErrorSelf Referencing Type

Contributing

Contributions are welcome - see the CONTRIBUTING.md file for details.

License

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

About

note

Generate primitive strongly typed wrapper around a single value object

How to use

Example (source csproj, source files)

This is the CSharp Project that references Monify

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Monify" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

namespace Monify
{
using System;
using System.Diagnostics.CodeAnalysis;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
internal sealed class MonifyAttribute<T>
: Attribute
{
}
}

Useful

Download Example (.NET C#)

Share Monify

https://ignatandrei.github.io/RSCG_Examples/v2/docs/Monify

Category "PrimitiveObsession" has the following generators:

1 DomainPrimitives NugetNuget GitHub Repo stars 2024-01-11

2 Monify Nuget GitHub Repo stars 2025-12-12

3 Strongly Nuget GitHub Repo stars 2023-08-19

4 StronglyTypedUid Nuget GitHub Repo stars 2024-04-07

5 UnitGenerator Nuget GitHub Repo stars 2023-10-15

6 Vogen Nuget GitHub Repo stars 2023-04-16

See category

PrimitiveObsession