Skip to content

DoubledDoge/typeguard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

93 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

TypeGuard

CI/CD CodeQL NuGet License: MIT .NET Downloads

A fluent, type-safe user input handler and validation library for .NET with platform-specific implementations for Console, WinForms, WPF, Avalonia, MAUI, and Blazor.


πŸ“‘ Table of Contents


πŸš€ Features

  • Type-Safe Validation - Built-in input handlers + validators for all common C# types
  • Composable Rules - Chain validation rules, similarly to LINQ
  • Async Support - Full async/await support with cancellation tokens
  • Extensible - Add custom handlers and rules with ease
  • Multi-Platform - Dedicated implementations for Console, WinForms, WPF, Avalonia, MAUI, and Blazor

πŸ“¦ Installation

Install only the package for your platform. TypeGuard.Core is included automatically as a dependency.

Console

dotnet add package TypeGuard.Console

WinForms

dotnet add package TypeGuard.Winforms

WPF

dotnet add package TypeGuard.Wpf

Avalonia

dotnet add package TypeGuard.Avalonia

MAUI

dotnet add package TypeGuard.Maui

Blazor

dotnet add package TypeGuard.Blazor

(Note: ASP.NET are planned but isn't fully ready yet)

Manual Installation

dotnet add reference path/to/TypeGuard.Console/TypeGuard.Console.csproj  # or your platform project

🎯 Quick Start

Console

using TypeGuard.Console;

int age = Guard.Int("Enter your age")
    .WithRange(1, 120)
    .Get();

string name = await Guard.String("Enter your name")
    .WithNoDigits()
    .WithLengthRange(2, 50)
    .GetAsync();

WinForms

using TypeGuard.Winforms;

private readonly Guard _guard;

public MyForm()
{
    InitializeComponent();
    _guard = new Guard(inputTextBox, promptLabel, errorLabel);
}

private async void submitButton_Click(object sender, EventArgs e)
{
    int age = await _guard.Int("Enter your age")
        .WithRange(1, 120)
        .GetAsync();
}

πŸ“š Usage Guide

Simple Input Handling

int count = await Guard.Int("How many items?").GetAsync();

string username = await Guard.String("Enter username").GetAsync();

DateTime date = await Guard.DateTime("Enter a date", "dd/MM/yyyy").GetAsync();

Adding Rules

int age = await Guard.Int("Enter your age")
    .WithRange(18, 120)
    .GetAsync();

string username = await Guard.String("Choose a username")
    .WithLengthRange(3, 20)
    .WithNoDigits()
    .GetAsync();

Custom Validation Rules

string password = await Guard.String("Create a password")
    .WithLengthRange(8, null)
    .WithRegex(@"[A-Z]", "Must contain at least one uppercase letter")
    .WithRegex(@"[a-z]", "Must contain at least one lowercase letter")
    .WithRegex(@"\d", "Must contain at least one digit")
    .WithCustomRule(
        p => p.Distinct().Count() >= 5,
        "Must contain at least 5 unique characters")
    .GetAsync();

DateTime Handling

DateTime appointment = await Guard.DateTime("Enter appointment date", "dd/MM/yyyy")
    .WithRange(DateTime.Today, DateTime.Today.AddMonths(6))
    .GetAsync();

DateTime birthday = await Guard.DateTime("Enter birthday")
    .WithCustomRule(
        d => DateTime.Today.Year - d.Year >= 18,
        "Must be 18 or older")
    .GetAsync();

DateTime meeting = await Guard.DateTime("Select meeting date", "yyyy-MM-dd")
    .WithWeekday()
    .GetAsync();

πŸ–₯️ Platform Guide

Console

using TypeGuard.Console;

int age = await Guard.Int("Enter your age")
    .WithRange(1, 120)
    .GetAsync();

string name = await Guard.String("Enter your name").GetAsync();

WinForms

using TypeGuard.Winforms;

private readonly Guard _guard;

public MyForm()
{
    InitializeComponent();
    _guard = new Guard(inputTextBox, promptLabel, errorLabel);
}

private async void submitButton_Click(object sender, EventArgs e)
{
    int age = await _guard.Int("Enter your age")
        .WithRange(1, 120)
        .GetAsync();
}

WPF

using TypeGuard.Wpf;

private readonly Guard _guard;

public MyWindow()
{
    InitializeComponent();
    _guard = new Guard(inputTextBox, promptBlock, errorBlock);
}

private async void SubmitButton_Click(object sender, RoutedEventArgs e)
{
    int age = await _guard.Int("Enter your age")
        .WithRange(1, 120)
        .GetAsync();
}

Avalonia

using TypeGuard.Avalonia;

private readonly Guard _guard;

public MyView()
{
    InitializeComponent();
    _guard = new Guard(InputTextBox, PromptBlock, ErrorBlock);
}

private async void SubmitButton_Click(object sender, RoutedEventArgs e)
{
    int age = await _guard.Int("Enter your age")
        .WithRange(1, 120)
        .GetAsync();
}

MAUI

using TypeGuard.Maui;

_guard = new Guard(InputEntry, PromptLabel, ErrorLabel, SubmitButton);

int age = await _guard.Int("Enter your age")
    .WithRange(1, 120)
    .GetAsync();

Blazor

@inject Guard Guard

<InputText @bind-Value="Guard.Input.Value" />
<p>@Guard.Output.PromptMessage</p>
<p style="color: red">@Guard.Output.ErrorMessage</p>

@code {
    protected override void OnInitialized()
    {
        Guard.Output.OnStateChanged = StateHasChanged;
    }

    private async Task SubmitAsync()
    {
        int age = await Guard.Int("Enter your age")
            .WithRange(1, 120)
            .GetAsync();
    }
}

πŸ—οΈ Architecture

TypeGuard.Core              β†’ Platform-agnostic logic
β”œβ”€β”€ Abstractions            β†’ Interfaces
β”œβ”€β”€ Handlers                β†’ Type-specific handlers
β”œβ”€β”€ Rules                   β†’ Validation rules
└── Builders                β†’ Fluent API builders

TypeGuard.Console           β†’ Console implementation
β”œβ”€β”€ ConsoleInput            β†’ Reads from Console.ReadLine()
β”œβ”€β”€ ConsoleOutput           β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

TypeGuard.Winforms          β†’ WinForms implementation (TextBox, TextBlock)
β”œβ”€β”€ WinformsInput           β†’ Reads from Control.Text
β”œβ”€β”€ WinformsOutput          β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

TypeGuard.Wpf               β†’ WPF implementation (TextBox, TextBlock)
β”œβ”€β”€ WpfInput                β†’ Reads from Textbox.Text
β”œβ”€β”€ WpfOutput               β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

TypeGuard.Avalonia          β†’ Avalonia implementation (TextBox, TextBlock)
β”œβ”€β”€ AvaloniaInput           β†’ Reads from Textbox.Text
β”œβ”€β”€ AvaloniaOutput          β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

TypeGuard.Maui              β†’ MAUI implementation (Entry, Label, Button)
β”œβ”€β”€ MauiInput               β†’ Reads from Entry.Text
β”œβ”€β”€ MauiOutput              β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

TypeGuard.Blazor            β†’ Blazor implementation (InputText, DI-injected Guard)
β”œβ”€β”€ BlazorInput             β†’ Reads from InputText.Value
β”œβ”€β”€ BlazorOutput            β†’ Writes prompts and errors
└── Guard                   β†’ Main entry point

πŸ”Œ Extending TypeGuard

Creating Custom Rules

using TypeGuard.Core.Interfaces;

public class EmailRule : IValidatorRule<string>
{
    public bool IsValid(string value) =>
        value.Contains('@') && value.Contains('.');

    public string ErrorMessage => "Must be a valid email address";
}
 
string email = await Guard.String("Enter email")
    .WithCustomRule(new EmailRule())
    .GetAsync();

// Note: Email Rule already exists but this is just an example of how to create your own custom rule.

πŸ’» Requirements

  • .NET 9.0 or .NET 10.0
  • Windows, macOS, or Linux (certain packages may have OS restrictions)

πŸ“„ License

See LICENCE for details. (MIT Licence)


🀝 Contributing

Contributions are welcome! You can:

  • Report bugs or request features via Issues
  • Submit pull requests
  • Suggest improvements to the API
  • Adding new type handlers/builders/rules

About

Another input handler and validation library for .NET applications.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages