MultiType.NET.Core
1.0.1
dotnet add package MultiType.NET.Core --version 1.0.1
NuGet\Install-Package MultiType.NET.Core -Version 1.0.1
<PackageReference Include="MultiType.NET.Core" Version="1.0.1" />
<PackageVersion Include="MultiType.NET.Core" Version="1.0.1" />
<PackageReference Include="MultiType.NET.Core" />
paket add MultiType.NET.Core --version 1.0.1
#r "nuget: MultiType.NET.Core, 1.0.1"
#addin nuget:?package=MultiType.NET.Core&version=1.0.1
#tool nuget:?package=MultiType.NET.Core&version=1.0.1
๐ฆ MultiType.NET
Type-safe, zero-allocation discriminated unions for modern .NET
Bring TypeScript-style union types to C# โ safer than object
, cleaner than if
, and built for real-world APIs and models.
Any<int, string> result = "hello";
๐ง What Is a Union Type?
A union type lets a value be one of multiple specified types โ like this in TypeScript:
let result = number | string | null
// C# with MultiType.NET
Any<int, string> result = "hello";
MultiType.NET brings that idea to C# with full support for:
- โ
Type-safe access (
Is<T>()
,As<T>()
,Match
) - โ JSON (de)serialization
- โ Zero boxing
- โ ASP.NET API compatibility
- โ Source generation for no-boilerplate code
โจ Features Overview
Category | Features |
---|---|
โ Matching | Match , TryMatch , Switch , SwitchAsync , SwitchOrDefault |
๐ Mapping | Map , MapAsync , MapSafe , MapValue , MapAny , MapWithContext , MapOrDefault , MapWhere |
๐ Selection | Select , TrySelect , SelectAsync , SelectAsyncOrDefault , SelectWithContext , SelectWhere |
๐ฆ Extraction | GetTn , TryGetTn , GetTn(out remainder) , Deconstruct(...) |
๐ง Introspection | ActualType , AllowedTypes , IsNull , ToString() |
โ๏ธ Construction | From , TryFrom , FromTn , implicit/explicit operators |
๐ค Serialization | Native System.Text.Json support (global or attribute-based) |
๐งโ๐ป API-Ready | Works with Controllers & Minimal APIs |
๐งฉ Generator | Auto-generates union types via [GenerateAny] or Any<T1..Tn> |
๐งฉ Model Binding | All types are Controller / Minimal-API Binding Ready |
๐ Get Started
๐ฆ Install Core Library
dotnet add package MultiType.NET.Core
This gives you:
Any<T1..T16>
prebuilt types- Core features like
Match
,Map
,Switch
,TryMatch
, ...etc - JSON support via converter factory
๐ง Add Optional Source Generators
Package | Description |
---|---|
MultiType.NET.Generator |
Adds [GenerateAny(typeof(...))] support |
MultiType.NET.SourceGenerator |
Enables Any<T1..Tn> (over 16 types), JSON support, API integration |
dotnet add package MultiType.NET.Generator
This allow you to generate a custom types with [GenerateAny]
, for more details MultiType.NET.Generator attribute.
[GenerateAny(typeof(string), typeof(MyType))]
public partial struct MyCustomType{}
This will generate MyCustomType
with all MultiType APIs.
Need to generate Any<T17, ..., Tn>
?
Install the official CLI generator:
dotnet tool install --global MultiType.NET.SourceGenerator
Then run:
multitypegen --maxArity 50 --project PATH_TO_TARGET_PROJECT.csproj
for more details and documentation MultiType.NET.SourceGenerator CLI
๐ก Learn by Example
Any<int, string, DateTime> result = "hello";
string output = result.Match(
i => $"Int: {i}",
s => $"String: {s}",
d => $"Date: {d:yyyy-MM-dd}"
);
// Using generic Any<T1, T2, T3> directly from body
[HttpPost("process-multi-type")]
public async Task<IActionResult> ProcessMultiTypeData(
[FromBody] Any<int, string, DateTime> requestData)
{
// Example usage: requestData.Match(...)
return Ok();
}
// Using generic Any<T1, T2, T3> from query string (less typical, but possible)
[HttpGet("query-multi-type")]
public async Task<IActionResult> QueryMultiTypeData(
[FromQuery] Any<int, string, DateTime> queryData)
{
return Ok();
}
if (result.TryGetT1(out var i, out var remainder))
Console.WriteLine($"Was int: {i}");
else
Console.WriteLine($"Not an int: {remainder}");
var summary = result.Select(
i => $"# {i}",
s => s.ToUpperInvariant(),
d => d.ToShortTimeString()
);
๐งฑ Creating Any Values
MultiType.NET offers multiple ways to construct union values.
โ
From(...)
โ dynamic dispatch
object raw = 123;
var value = Any<int, string, DateTime>.From(raw);
๐ก Throws if the value is not one of the allowed types.
โ
TryFrom(...)
โ safe version
if (Any<int, string>.TryFrom(someValue, out var result))
{
// Use result
}
โ
FromTn(...)
โ type-specific creation
var a = Any<int, string, bool>.FromT1(42);
var b = Any<int, string, bool>.FromT2("hello");
๐ก These are especially useful for code generation, dynamic input handling, or overload clarity.
โ Implicit Operators
Any<int, string> v1 = 5;
Any<int, string> v2 = "done";
๐ฆ JSON Serialization
MultiType.NET works seamlessly with System.Text.Json
without any manual changes.
โ Per-type registration
public readonly partial struct MyUnionType;
๐งช Example
var options = new JsonSerializerOptions { WriteIndented = true };
string json = JsonSerializer.Serialize(Any<int, string>.From(123), options);
๐ก JSON output includes both the value and the represented type.
๐งฉ Custom Types with [GenerateAny]
โ ๏ธ Requires
MultiType.NET.Generator
installed.
[GenerateAny(typeof(int), typeof(string), typeof(Guid))]
public partial struct Payload;
// POST endpoint accepting Payload from body
[HttpPost("submit-payload")]
public async Task<IActionResult> SubmitPayload(
[FromBody] Payload payload)
{
// payload.Match(...)
return Ok();
}
// GET endpoint accepting Payload from query
[HttpGet("search")]
public async Task<IActionResult> SearchPayload(
[FromQuery] Payload query)
{
return Ok();
}
Payload payload = Guid.NewGuid();
payload.Match(
i => Console.WriteLine($"Int: {i}"),
s => Console.WriteLine($"Str: {s}"),
g => Console.WriteLine($"Guid: {g}")
);
** More advanced Type**
[GenerateAny(typeof(Success), typeof(Warning), typeof(Error), typeof(Info))]
public partial struct StatusType
{
public static StatusType From(string value) => value.ToLowerInvariant() switch
{
"success" => new Success(),
"warning" => new Warning(),
"error" => new Error(),
"info" => new Info(),
_ => throw new ArgumentException("Invalid status", nameof(value))
};
public bool IsSuccess => this.Is<Success>();
public bool IsWarning => this.Is<Warning>();
public bool IsError => this.Is<Error>();
public bool IsInfo => this.Is<Info>();
public readonly struct Success { }
public readonly struct Warning { }
public readonly struct Error { }
public readonly struct Info { }
}
โ๏ธ How It Works (Behind the Scenes)
Any<T1, ..., Tn>
is a readonly struct with internal value/ref handling.- Tracks active type via
TypeIndex
- Source generators:
- Generate custom union types with all logic
- Auto-wire JSON support
- Add full method surface (Match, Map, Select, etc.)
๐งช Real-World Use Cases
Use Case | Example |
---|---|
โ API Results | Any<SuccessDto, ErrorDto> |
๐งโโ๏ธ Workflow Results | Any<Approved, Rejected, Escalated> |
๐ง State Modeling | Any<Draft, Submitted, Published> |
๐งพ Flexible Inputs | Any<string, int, bool> |
๐ Retry Backoff | Any<RetryLater, Fail, Success> |
๐ Project Structure
Project | Description |
---|---|
MultiType.NET.Core |
Runtime types and logic |
MultiType.NET.Generator |
[GenerateAny] source generation |
MultiType.NET.SourceGenerator |
JSON + Any<T1..Tn> generation |
๐ Documentation
Resource | Link |
---|---|
๐ Advanced Features | docs/AdvancedFeatures.md |
๐ง Generator Guide | docs/SourceGenerators.md |
๐ก Integration Tips | docs/Integration.md |
๐ Contributing
Contributions, issues, and PRs are welcome!
See CONTRIBUTING.md
to get started.
๐ License
MIT โ LICENSE
Because type safety shouldn't be optional.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. 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. |
-
net8.0
- No dependencies.
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.1 | 115 | 7/2/2025 |