WS.DomainModelling
1.0.15
dotnet add package WS.DomainModelling --version 1.0.15
NuGet\Install-Package WS.DomainModelling -Version 1.0.15
<PackageReference Include="WS.DomainModelling" Version="1.0.15" />
<PackageVersion Include="WS.DomainModelling" Version="1.0.15" />
<PackageReference Include="WS.DomainModelling" />
paket add WS.DomainModelling --version 1.0.15
#r "nuget: WS.DomainModelling, 1.0.15"
#:package WS.DomainModelling@1.0.15
#addin nuget:?package=WS.DomainModelling&version=1.0.15
#tool nuget:?package=WS.DomainModelling&version=1.0.15
WS.DomainModelling
A C# source generator for F# style discriminated unions and basic wrapper types, inspired by Domain Modeling Made Functional by Scott Wlaschin.
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 Option 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
partial, this allows the code generator to place the generated code in a different file - Create a
private staticmethod that accepts a value of the wrapped type as an argument and returns abool - Add the
BasicWrapperattribute, 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
Createstatic method to generate a new value, anOptioninstance is returned - For convenience, use the
BindandMapmethods 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
partial, this allows the code generator to place the generated code in a different file - For each option add an instance of the
Optionattribute - The type of any data associated with an option can be specified by the
OfGenericandOfTypeattribute constructor parameters - An option can specify either
OfGenericorOfType, 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
SwitchandMatchmethods
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}")
);
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- WS.DomainModelling.Common (>= 1.0.15)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.