WS.DomainModelling 1.0.11

dotnet add package WS.DomainModelling --version 1.0.11
                    
NuGet\Install-Package WS.DomainModelling -Version 1.0.11
                    
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="WS.DomainModelling" Version="1.0.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WS.DomainModelling" Version="1.0.11" />
                    
Directory.Packages.props
<PackageReference Include="WS.DomainModelling" />
                    
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 WS.DomainModelling --version 1.0.11
                    
#r "nuget: WS.DomainModelling, 1.0.11"
                    
#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 WS.DomainModelling@1.0.11
                    
#: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=WS.DomainModelling&version=1.0.11
                    
Install as a Cake Addin
#tool nuget:?package=WS.DomainModelling&version=1.0.11
                    
Install as a Cake Tool

WS.DomainModelling

Test out dotnet code generation to create a genearator for F# style discriminated unions in C#

Inspiration

BasicWrapper

Basic Wrapper generates a class that wraps a single type with validation logic. The class has a Create method that takes a value of the wrapped type, and returns an <code>Option</code> of the wrapping type. This has two advantages. The caller is forced to deal with an invalid value when an instance of the wrapping type is created and the caller also knows that once created the wrapper instance can be passed to other methods and will always hold a valid value.

Definition

  • Mark the wrapping class <code>partial</code>, this allows the code generator to place the generated code in a different file
  • Create a <code>private static</code> method that accepts a value of the wrapped type as an argument and returns a <code>bool</code>
  • Add the <code>BasicWrapper</code> attribute, and specify the wrapped type and the name of the validating method
[BasicWrapper(typeof(int), nameof(Validate))]
public partial class NaturalInteger
{
    private static bool Validate(int value) => value >= 0;
}

Usage

  • Use the generated <code>Create</code> static method to generate a new value, an <code>Option</code> instance is returned
  • For convenience, use the <code>Bind</code> and <code>Map</code> methods to access the value.
public record Score(NaturalInteger Home, NaturalInteger Away);
...
Option<Score> score = NaturalInteger
    .Create(5)
    .Bind(home => NaturalInteger
        .Create(2)
        .Map(away => new Score(home, away)));

Discriminated Union

Definition

  • Mark the union class <code>partial</code>, this allows the code generator to place the generated code in a different file
  • For each option add an instance of the <code>Option</code> attribute
  • The type of any data associated with an option can be specified by the <code>OfGeneric</code> and <code>OfType</code> attribute constructor parameters
  • An option can specify either <code>OfGeneric</code> or <code>OfType</code>, or neither, but not both
[Option("Success", OfGeneric = "Q")]
[Option("Failed")]
[Option("FileNotFoundError", OfType = typeof(string))]
[Option("IndexOutOfBoundsError", OfType = typeof((int AnInt, string)))]
public partial class DetailedResult<Q>
{
}

Usage

  • Static methods and properties are generated to create new instances.
  • Access the option using the <code>Switch</code> and <code>Match</code> methods
DetailedResult<List<string>> DoSomething()
{
    var index = ...
    if (...)
    {
        return DetailedResult<List<string>>.IndexOutOfBoundsError((index, "Message"));
    }
    if (...)
    {
        return DetailedResult<List<string>>.FileNotFoundError("Message");
    }
    var messages = ...
    if (...)
    {
        return DetailedResult<List<string>>.Failed;
    }
    return DetailedResult<List<string>>.Success(messages);
}
...
var result = DoSomething();
result.Switch(
    messages => Console.WriteLine(string.Join(", ", messages)),
    () => Console.WriteLine("Failed"),
    message => Console.WriteLine($"File not found {message}"),
    result => Console.WriteLine($"Index {result.AnInt} out of range: {result.Item2}")
);
There are no supported framework assets in this 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
1.0.11 180 12/3/2025
1.0.10 645 12/3/2025
1.0.9 653 12/2/2025
1.0.8 184 10/29/2025
1.0.7 154 7/31/2025
1.0.6 135 7/30/2025
1.0.4 138 7/12/2025
1.0.3 177 7/3/2025
1.0.2 166 7/3/2025