├── icon.png ├── toolbox.ico ├── ToolboxTopService ├── icon.png ├── GlobalUsings.cs ├── ToolboxTopService.csproj ├── README.md ├── HostApplicationBuilderExtension.cs └── TopServiceBuilder.cs ├── WpfTools ├── Images │ └── question.png ├── README.md ├── Services │ └── IDialogService.cs ├── Dialogs │ ├── DialogWindow.xaml.cs │ ├── AskInputDialogView.xaml.cs │ ├── DialogViewModel.cs │ ├── AskInputDialogViewModel.cs │ ├── DialogWindow.xaml │ └── AskInputDialogView.xaml ├── BaseModels │ ├── Interfaces.cs │ ├── BaseViewModelClose.cs │ ├── BaseViewModel.cs │ └── BaseNotifier.cs ├── Commands │ ├── OpenWindowCommand.cs │ ├── OpenDialogCommand.cs │ ├── DelegateCommand.cs │ ├── BaseCommand.cs │ ├── ShowWindowCommand.cs │ └── AsyncDelegateCommand.cs ├── Helpers │ ├── ProgressEventArgs.cs │ ├── MessageBoxHelper.cs │ ├── ProgressHelper.cs │ └── WindowCloser.cs ├── BaseNav │ ├── NavigationSetupService.cs │ └── ViewStuff.cs ├── Extensions │ ├── CurrentCultureHelper.cs │ ├── ImageExtensions.cs │ └── LocalizedDescriptionAttribute.cs ├── Converters │ ├── Converters.xaml │ ├── Multiply.cs │ ├── ObjectToJson.cs │ ├── BoolToVisibilityInvers.cs │ ├── IntToString.cs │ ├── BoolToVisibility.cs │ ├── TimespanToString.cs │ ├── EnumTypeConverter.cs │ └── ImageToImageSource.cs ├── WindowStuff │ └── IWindowService.cs ├── Controls │ ├── SliderMenuItem.xaml │ └── CustomSlider.cs ├── MarkupExtensions │ └── EnumBindingSourceExtension.cs ├── Resources.xaml ├── AssemblyInfo.cs ├── WpfTools.csproj └── readme.txt ├── ConsoleTools ├── GlobalUsings.cs ├── Power │ ├── Spectre │ │ ├── ProgressTask.cs │ │ ├── Json.cs │ │ ├── Status.cs │ │ └── Progress.cs │ ├── Commands │ │ ├── Position.cs │ │ └── Window.cs │ ├── Input │ │ ├── Decision.cs │ │ ├── InputHelpers.cs │ │ ├── ClassBasedSelection.cs │ │ └── Text.cs │ └── Shutdown │ │ └── CancelKeyPressHandler.cs ├── README.md ├── Progress │ ├── ConsoleInlineProgressBar.cs │ └── ConsoleTopProgressBar.cs ├── BootstrapperExtensions.cs ├── Interop │ ├── WindowVisibility.cs │ └── PowerShellHelper.cs ├── SpectreInfrastructure │ ├── ServiceCollectionTypeResolver.cs │ ├── ServiceCollectionTypeRegistrar.cs │ └── AppTypeRegistrar.cs └── ConsoleTools.csproj ├── ToolboxImage ├── Resources │ └── icon.png ├── README.md ├── LICENSE.md ├── Contracts │ ├── IFixedImageInImage.cs │ └── IImageInImage.cs ├── Configuration │ └── FixedImageInImageSettings.cs ├── GlobalUsings.cs ├── ToolboxImage.csproj ├── Model │ ├── FixedImageInImage.cs │ └── Enums │ │ └── ImageScaleMode.cs ├── Extensions │ └── ImageInImageExtensions.cs └── NOTICE.md ├── ToolboxConsole ├── Resources │ └── icon.png ├── README.md ├── CommandApp │ ├── ScTypeResolver.cs │ └── AppTypeRegistrar.cs ├── LICENSE.md ├── ToolboxConsole.csproj └── NOTICE.md ├── WebTools ├── WebToolsAssemblyMarker.cs ├── Configuration │ ├── CertSettingsBase.cs │ └── OidcSettingsBase.cs ├── Properties │ └── launchSettings.json ├── webtools-schema.json ├── Filter │ └── ValidationFilter.cs ├── Models │ └── ErrorResponse.cs ├── Authorization │ └── AllowedClients.cs ├── Cors │ ├── readme.md │ ├── CorsAttributes.cs │ └── CorsExtensions.cs ├── Exceptions │ └── BadRequestException.cs ├── Extensions │ └── ContextExtensions.cs ├── WebTools.csproj ├── README.md ├── Authentication │ └── AlwaysSucceedAuthenticationHandler.cs └── Middleware │ └── BearerToHeaderMiddleware.cs ├── ToolboxAppOptions ├── Resources │ └── icon.png ├── ISettingsBase.cs ├── GlobalUsings.cs ├── Configuration │ ├── ToolboxAppOptionsSettings.cs │ └── ToolboxAppOptionsSettingsBuilder.cs ├── Services │ ├── AppOptionsTransformationService.cs │ └── StartupValidationService.cs ├── ToolboxAppOptions.csproj └── Transformations │ └── ProtectedTransformer.cs ├── ToolboxFluentValidation ├── GlobalUsings.cs ├── Resources │ └── icon.png ├── README.md ├── LICENSE.md ├── NOTICE.md └── ToolboxFluentValidation.csproj ├── global.json ├── Tests ├── ToolboxTests │ ├── Resources │ │ ├── 1680_525.jpg │ │ └── 840_1050.jpg │ ├── BootstrapperExtensionsTests.cs │ ├── ToolboxTests.csproj │ ├── GeoTools │ │ └── GeoServiceTests.cs │ ├── InteropTests │ │ └── WallpaperHelperTests.cs │ └── SecurityTests │ │ └── VirusScanServiceTests.cs ├── WpfToolsManualTests │ ├── ViewModel │ │ ├── TestViewModel.cs │ │ ├── TestManualDialogViewModel.cs │ │ └── MainWindowViewModel.cs │ ├── View │ │ ├── MainWindow.xaml.cs │ │ ├── TestWindow.xaml.cs │ │ ├── TestManualDialogView.xaml.cs │ │ ├── TestWindow.xaml │ │ ├── MainWindow.xaml │ │ └── TestManualDialogView.xaml │ ├── App.xaml │ ├── WpfToolsManualTests.csproj │ └── App.xaml.cs ├── Directory.Build.props ├── ToolboxTopServiceManualTests │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ ├── GlobalUsings.cs │ ├── ToolboxTopServiceManualTests.csproj │ └── SampleService.cs ├── ExtensionsTests │ ├── MonadExtensionTests │ │ └── MappingTests.cs │ ├── CryptoExtensionsTests │ │ ├── Base64StuffTests.cs │ │ └── HexStuffTests.cs │ ├── NumberExtensionsTests │ │ └── ComparisonExtensionsTests.cs │ ├── FileExtensionsTests │ │ └── StorageSizeStuffTests.cs │ ├── ExtensionsTests.csproj │ ├── TimeExtensionsTests │ │ └── ComparisonExtensionsTests.cs │ └── TextExtensionsTests │ │ └── RegexExtensionsTests.cs ├── ConsoleToolsManualTests │ └── ConsoleToolsManualTests.csproj ├── ToolboxAppOptionsTests │ ├── GlobalUsings.cs │ ├── Configuration │ │ └── ToolboxAppOptionsSettingsTests.cs │ ├── appsettings.json │ ├── Bases │ │ └── AppOptionTestBase.cs │ ├── ToolboxAppOptionsTests.csproj │ └── Transformations │ │ ├── PlaceholderTransformationTests.cs │ │ └── ProtectedTransformerTests.cs └── WpfToolsTests │ └── WpfToolsTests.csproj ├── Extensions ├── README.md ├── MonadExtensions │ └── Mapping.cs ├── TypeExtensions.cs ├── ExceptionExtensions │ └── ReadingStuff.cs ├── TextExtensions │ ├── FormattingExtensions.cs │ └── Parsing.cs ├── FileExtensions │ ├── FileSystemStuff.cs │ ├── StorageSizeStuff.cs │ └── HashStuff.cs ├── StorageExtensions │ ├── ReflectionStuff.cs │ └── FileOpsExtensions.cs ├── TimeExtensions │ ├── TimingExtensions.cs │ └── CalculationExtensions.cs ├── VersionExtensions │ └── VersionExtensions.cs ├── Extensions.csproj ├── CryptoExtensions │ ├── HexStuff.cs │ └── ByteStuff.cs ├── NetworkExtensions │ └── IpAddressExtensions.cs ├── NumberExtensions │ └── ComparisonExtensions.cs ├── DictionaryExtensions.cs ├── OwinExtensions │ └── ClaimExtensions.cs └── StringManipulationExtensions.cs ├── Toolbox ├── SerializationTools │ ├── ITypeToFileStore.cs │ ├── JsonExtensions.cs │ ├── TypeToFileValue.cs │ └── EmbeddedResourceQuery.cs ├── NetworkTools │ ├── IgnoreServerCertificateHandler.cs │ └── Internet.cs ├── README.md ├── CustomDatastructures │ └── DropOutStack.cs ├── SortTools │ └── NaturalSort.cs ├── Oidc │ └── SessionStore.cs ├── GeoTools │ └── GeoService.cs ├── SecurityTools │ └── SslHelper.cs ├── SyncTools │ └── AppSingleStartup.cs ├── Ioc │ └── DecoratorRegistrationExtensions.cs └── _Obsolete │ └── RegistryEditor.cs ├── version.json ├── README.md ├── aemarcoCommons.sln.DotSettings └── LICENSE.md /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/icon.png -------------------------------------------------------------------------------- /toolbox.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/toolbox.ico -------------------------------------------------------------------------------- /ToolboxTopService/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/ToolboxTopService/icon.png -------------------------------------------------------------------------------- /WpfTools/Images/question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/WpfTools/Images/question.png -------------------------------------------------------------------------------- /ConsoleTools/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | 4 | global using Spectre.Console; 5 | global using System; -------------------------------------------------------------------------------- /ToolboxImage/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/ToolboxImage/Resources/icon.png -------------------------------------------------------------------------------- /ToolboxConsole/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/ToolboxConsole/Resources/icon.png -------------------------------------------------------------------------------- /WebTools/WebToolsAssemblyMarker.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.WebTools; 2 | public class WebToolsAssemblyMarker 3 | { 4 | } 5 | -------------------------------------------------------------------------------- /ToolboxAppOptions/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/ToolboxAppOptions/Resources/icon.png -------------------------------------------------------------------------------- /ToolboxFluentValidation/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using FluentValidation; 4 | global using System; -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.304", 4 | "rollForward": "minor", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /Tests/ToolboxTests/Resources/1680_525.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/Tests/ToolboxTests/Resources/1680_525.jpg -------------------------------------------------------------------------------- /Tests/ToolboxTests/Resources/840_1050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/Tests/ToolboxTests/Resources/840_1050.jpg -------------------------------------------------------------------------------- /ToolboxFluentValidation/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aemarco/aemarcoCommons/HEAD/ToolboxFluentValidation/Resources/icon.png -------------------------------------------------------------------------------- /WpfTools/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoWpfTools` 2 | 3 |
4 | -------------------------------------------------------------------------------- /Extensions/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoExtensions` 2 | 3 |
4 | -------------------------------------------------------------------------------- /ToolboxImage/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoToolboxImage` 2 | 3 |
4 | -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/ViewModel/TestViewModel.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | 3 | namespace WpfToolsManualTests.ViewModel; 4 | internal class TestViewModel : BaseViewModel; 5 | -------------------------------------------------------------------------------- /ToolboxConsole/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoToolboxConsole` 2 | 3 |
4 | -------------------------------------------------------------------------------- /WpfTools/Services/IDialogService.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.WpfTools.Services; 2 | public interface IDialogService 3 | { 4 | 5 | 6 | 7 | bool ShowDialog(object viewModel); 8 | 9 | 10 | 11 | } -------------------------------------------------------------------------------- /Tests/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | enable 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Tests/ToolboxTopServiceManualTests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ToolboxTopServiceManualTests": { 4 | "commandName": "Project", 5 | "commandLineArgs": "" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/View/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace WpfToolsManualTests.View; 2 | 3 | public partial class MainWindow 4 | { 5 | public MainWindow() 6 | { 7 | InitializeComponent(); 8 | } 9 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/View/TestWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace WpfToolsManualTests.View; 2 | 3 | public partial class TestWindow 4 | { 5 | public TestWindow() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ToolboxFluentValidation/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoToolboxFluentValidation` 2 | 3 |
4 | 5 | -------------------------------------------------------------------------------- /ToolboxTopService/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using CliWrap; 4 | global using CliWrap.Buffered; 5 | global using Microsoft.Extensions.Hosting; 6 | global using System; 7 | global using System.Threading.Tasks; -------------------------------------------------------------------------------- /WpfTools/Dialogs/DialogWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.WpfTools.Dialogs; 2 | 3 | public partial class DialogWindow 4 | { 5 | public DialogWindow() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WpfTools/Dialogs/AskInputDialogView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.WpfTools.Dialogs; 2 | 3 | public partial class AskInputDialogView 4 | { 5 | public AskInputDialogView() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Extensions/MonadExtensions/Mapping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.Extensions.MonadExtensions; 4 | 5 | public static class Mapping 6 | { 7 | public static TOut Map(this TIn @this, Func f) => 8 | f(@this); 9 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/View/TestManualDialogView.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace WpfToolsManualTests.View; 2 | 3 | public partial class TestManualDialogView 4 | { 5 | public TestManualDialogView() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /WebTools/Configuration/CertSettingsBase.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.WebTools.Configuration; 2 | 3 | public class CertSettingsBase 4 | { 5 | public string? Authority { get; init; } 6 | public string? Path { get; init; } 7 | public string? Pwd { get; init; } 8 | } -------------------------------------------------------------------------------- /Toolbox/SerializationTools/ITypeToFileStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.Toolbox.SerializationTools; 4 | 5 | public interface ITypeToFileStore : IDisposable 6 | where T : class, ITypeToFileValue, new() 7 | { 8 | T Instance { get; } 9 | T CommitReset(); 10 | void SaveChanges(); 11 | } -------------------------------------------------------------------------------- /WpfTools/BaseModels/Interfaces.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace aemarcoCommons.WpfTools.BaseModels; 4 | 5 | public interface IBaseNotifier : INotifyPropertyChanged; 6 | 7 | public interface IBaseViewModel : IBaseNotifier; 8 | 9 | public interface IWindow 10 | { 11 | void Show(); 12 | bool? ShowDialog(); 13 | } -------------------------------------------------------------------------------- /Tests/ToolboxTopServiceManualTests/Program.cs: -------------------------------------------------------------------------------- 1 | await Host.CreateApplicationBuilder(args) 2 | .SetupSampleService() 3 | .RunAsTopService(x => x 4 | .ServiceName("SomeService") 5 | .DisplayName("Some Service") 6 | .Description("SampleService installed with TopService") 7 | .StartupType(StartupType.AutoDelayed)); -------------------------------------------------------------------------------- /WebTools/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "WebTools": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "https://localhost:62751;http://localhost:62752" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Tests/ToolboxTopServiceManualTests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using aemarcoCommons.ToolboxTopService; 4 | global using Microsoft.Extensions.DependencyInjection; 5 | global using Microsoft.Extensions.Hosting; 6 | global using System; 7 | global using System.Threading; 8 | global using System.Threading.Tasks; 9 | global using ToolboxTopServiceManualTests; -------------------------------------------------------------------------------- /Toolbox/NetworkTools/IgnoreServerCertificateHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | 3 | namespace aemarcoCommons.Toolbox.NetworkTools; 4 | 5 | public class IgnoreServerCertificateHandler : HttpClientHandler 6 | { 7 | public IgnoreServerCertificateHandler() 8 | { 9 | ServerCertificateCustomValidationCallback = 10 | (_, _, _, _) => true; 11 | } 12 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ConsoleTools/Power/Spectre/ProgressTask.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace aemarcoCommons.ConsoleTools; 3 | 4 | public static partial class PowerConsole 5 | { 6 | 7 | public static void CompleteTask(this ProgressTask task) 8 | { 9 | task.Value = task.MaxValue; 10 | task.IsIndeterminate = false; 11 | task.StopTask(); 12 | } 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /ConsoleTools/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoConsoleTools` 2 | 3 |
4 | 5 | 6 | ## Overview 7 | 8 | - Heavily makes use of Spectre.Console (https://spectreconsole.net/) 9 | 10 | ## Get Started 11 | 12 | - Use PowerConsole.... which brings a lot of stuff with it. 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "9.0", 4 | "versionHeightOffset": 6, 5 | "publicReleaseRefSpec": [ 6 | "^refs/heads/main", 7 | "^refs/heads/v\\d+(?:\\.\\d+)?$" 8 | ], 9 | "cloudBuild": { 10 | "buildNumber": { 11 | "enabled": true 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ConsoleTools/Power/Spectre/Json.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Spectre.Console.Json; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace aemarcoCommons.ConsoleTools; 6 | 7 | public static partial class PowerConsole 8 | { 9 | public static void WriteAsJson(object o) 10 | { 11 | AnsiConsole.Write(new JsonText(JsonConvert.SerializeObject(o))); 12 | AnsiConsole.WriteLine(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Tests/ExtensionsTests/MonadExtensionTests/MappingTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.MonadExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | 5 | namespace ExtensionsTests.MonadExtensionTests; 6 | 7 | public class MappingTests 8 | { 9 | [Test] 10 | public void Map_Maps() 11 | { 12 | var r = 5.Map(x => x * 2); 13 | r.Should().Be(10); 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | } -------------------------------------------------------------------------------- /Tests/ConsoleToolsManualTests/ConsoleToolsManualTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net9.0-windows 6 | Exe 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Tests/ToolboxAppOptionsTests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | // Global using directives 2 | 3 | global using aemarcoCommons.ToolboxAppOptions; 4 | global using FluentAssertions; 5 | global using FluentValidation; 6 | global using Microsoft.Extensions.Configuration; 7 | global using Microsoft.Extensions.DependencyInjection; 8 | global using Microsoft.Extensions.Options; 9 | global using NUnit.Framework; 10 | global using System; 11 | global using ToolboxAppOptionsTests.Bases; -------------------------------------------------------------------------------- /WpfTools/Dialogs/DialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System; 3 | 4 | namespace aemarcoCommons.WpfTools.Dialogs; 5 | 6 | public class DialogViewModel : ObservableObject 7 | { 8 | 9 | public virtual string Title => "Title"; 10 | 11 | public event EventHandler? CloseDialog; 12 | protected virtual void OnCloseDialog(bool? dialogResult) => 13 | CloseDialog?.Invoke(this, dialogResult); 14 | 15 | } -------------------------------------------------------------------------------- /Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace aemarcoCommons.Extensions; 5 | 6 | public static class TypeExtensions 7 | { 8 | public static string GetReadableTypeName(this Type type) 9 | { 10 | var result = type.IsGenericType 11 | ? $"{type.Name.Split('`')[0]}<{string.Join(",", type.GetGenericArguments().Select(x => x.Name))}>" 12 | : type.Name; 13 | return result; 14 | } 15 | } -------------------------------------------------------------------------------- /Extensions/ExceptionExtensions/ReadingStuff.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.Extensions.ExceptionExtensions; 4 | 5 | public static class ReadingStuff 6 | { 7 | 8 | public static Exception Unpack(this Exception exception) 9 | { 10 | var result = exception; 11 | while (result?.InnerException != null) 12 | { 13 | result = result.InnerException; 14 | } 15 | return result; 16 | } 17 | 18 | 19 | 20 | 21 | } -------------------------------------------------------------------------------- /WebTools/webtools-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "type": "object", 4 | "definitions": { 5 | //"WebPipeSettings": { 6 | // "type": "object", 7 | // "properties": { 8 | // "UseDeveloperExceptionPage": { 9 | // "type": "boolean", 10 | // "description": "Enables DeveloperExceptionPage" 11 | // } 12 | // }, 13 | // "required": [ "UseDeveloperExceptionPage" ] 14 | //} 15 | } 16 | } -------------------------------------------------------------------------------- /ConsoleTools/Power/Commands/Position.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace aemarcoCommons.ConsoleTools; 3 | 4 | public static partial class PowerConsole 5 | { 6 | public static void ClearCurrentLine() 7 | { 8 | var currentLineCursor = Console.CursorTop; 9 | Console.SetCursorPosition(0, Console.CursorTop); 10 | Console.Write(new string(' ', Console.WindowWidth)); 11 | Console.SetCursorPosition(0, currentLineCursor); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Extensions/TextExtensions/FormattingExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Linq; 3 | 4 | namespace aemarcoCommons.Extensions.TextExtensions; 5 | 6 | public static class FormattingExtensions 7 | { 8 | public static string PrettifyXml(this string xml) 9 | { 10 | return XElement.Parse(xml).ToString(); 11 | } 12 | 13 | 14 | public static bool IsAbsoluteUri(this string uri) 15 | { 16 | return Uri.TryCreate(uri, UriKind.Absolute, out _); 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /WpfTools/Commands/OpenWindowCommand.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System; 4 | 5 | namespace aemarcoCommons.WpfTools.Commands; 6 | 7 | public class OpenWindowCommand : DelegateCommand 8 | where T : IWindow 9 | { 10 | public OpenWindowCommand(IServiceProvider serviceProvider) 11 | { 12 | CommandAction = _ => 13 | { 14 | serviceProvider.GetRequiredService().Show(); 15 | }; 16 | } 17 | } -------------------------------------------------------------------------------- /WpfTools/Commands/OpenDialogCommand.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System; 4 | 5 | namespace aemarcoCommons.WpfTools.Commands; 6 | 7 | public class OpenDialogCommand : DelegateCommand 8 | where T : IWindow 9 | { 10 | public OpenDialogCommand(IServiceProvider serviceProvider) 11 | { 12 | CommandAction = _ => 13 | { 14 | serviceProvider.GetRequiredService().ShowDialog(); 15 | }; 16 | } 17 | } -------------------------------------------------------------------------------- /Toolbox/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoToolbox` 2 | 3 |
4 | 5 | ## Table of Contents 6 | 7 | 1. [Packages](#packages) 8 | 9 | 10 | ## Packages 11 | 12 | [CliWrap](https://github.com/Tyrrrz/CliWrap) is a library for interacting with external command line interfaces. It provides a convenient model for launching processes, redirecting input and output streams, awaiting completion, handling cancellation, and more. 13 | 14 | 15 | -------------------------------------------------------------------------------- /ToolboxAppOptions/ISettingsBase.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.ToolboxAppOptions; 2 | 3 | /// 4 | /// This interface is to mark setting classes, so they get recognized as such 5 | /// 6 | public interface ISettingsBase; 7 | 8 | /// 9 | /// Custom Path in IConfiguration 10 | /// ex. empty string means root, 11 | /// ex. "Abc:Def" 12 | /// 13 | [AttributeUsage(AttributeTargets.Class)] 14 | public class SettingsPathAttribute(string path) : Attribute 15 | { 16 | public readonly string Path = path; 17 | } -------------------------------------------------------------------------------- /ConsoleTools/Power/Spectre/Status.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace aemarcoCommons.ConsoleTools; 5 | 6 | public static partial class PowerConsole 7 | { 8 | public static async Task StartStatusAsync( 9 | Func> work) 10 | { 11 | return await AnsiConsole.Status() 12 | .SpinnerStyle(Style.Parse("green")) 13 | .StartAsync( 14 | "[purple]Doing stuff...[/]", 15 | work); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ConsoleTools/Power/Commands/Window.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.ConsoleTools.Interop; 2 | using System.Runtime.Versioning; 3 | 4 | // ReSharper disable once CheckNamespace 5 | namespace aemarcoCommons.ConsoleTools; 6 | 7 | public static partial class PowerConsole 8 | { 9 | 10 | [SupportedOSPlatform("windows")] 11 | public static void ShowWindow() 12 | { 13 | WindowVisibility.Show(); 14 | } 15 | 16 | [SupportedOSPlatform("windows")] 17 | public static void HideWindow() 18 | { 19 | WindowVisibility.Hide(); 20 | } 21 | } -------------------------------------------------------------------------------- /Tests/ToolboxTopServiceManualTests/ToolboxTopServiceManualTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net9.0-windows 6 | enable 7 | false 8 | 9 | SomeServiceTest 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/WpfToolsManualTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net9.0-windows10.0.19041.0 7 | 10.0 8 | 9 | WinExe 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /WebTools/Filter/ValidationFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | 4 | namespace aemarcoCommons.WebTools.Filter; 5 | 6 | public class ValidationFilter : IActionFilter 7 | { 8 | public void OnActionExecuting(ActionExecutingContext context) 9 | { 10 | if (!context.ModelState.IsValid) 11 | { 12 | context.Result = new BadRequestObjectResult(context.ModelState); 13 | } 14 | } 15 | 16 | public void OnActionExecuted(ActionExecutedContext context) 17 | { 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /Extensions/FileExtensions/FileSystemStuff.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | 4 | namespace aemarcoCommons.Extensions.FileExtensions; 5 | 6 | public static class FileSystemStuff 7 | { 8 | public static Process OpenFileOrFolder(this FileInfo fileOrFolderPath) 9 | { 10 | var result = new Process 11 | { 12 | StartInfo = new ProcessStartInfo(fileOrFolderPath.FullName) 13 | { 14 | UseShellExecute = true 15 | } 16 | }; 17 | result.Start(); 18 | return result; 19 | } 20 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/View/TestWindow.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 12 | 13 | -------------------------------------------------------------------------------- /Extensions/StorageExtensions/ReflectionStuff.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Reflection; 3 | 4 | namespace aemarcoCommons.Extensions.StorageExtensions; 5 | 6 | public static class ReflectionStuff 7 | { 8 | 9 | public static string GetEntryDirectory() 10 | { 11 | return Assembly.GetEntryAssembly().GetDirectory(); 12 | } 13 | 14 | 15 | public static string GetDirectory(this Assembly assembly) 16 | { 17 | var assemblyLocation = assembly.Location; 18 | var di = new FileInfo(assemblyLocation).Directory; 19 | return di?.FullName; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /Tests/ExtensionsTests/CryptoExtensionsTests/Base64StuffTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.CryptoExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | 5 | namespace ExtensionsTests.CryptoExtensionsTests; 6 | 7 | public class Base64StuffTests 8 | { 9 | 10 | [TestCase("test", "CY9rzUYh03PK3k6DJie09g==")] 11 | [TestCase("oMyDear", "d7gPbeNldisHAEjR9Zq7OQ==")] 12 | public void ToBase64HashString_Returns_Correctly(string text, string expected) 13 | { 14 | 15 | var result = text.ToBase64HashString(); 16 | result.Should().Be(expected); 17 | } 18 | 19 | 20 | } -------------------------------------------------------------------------------- /ConsoleTools/Progress/ConsoleInlineProgressBar.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace aemarcoCommons.ConsoleTools; 3 | 4 | /// 5 | /// This progress bar fits, if console outputs are written in between progress steps 6 | /// 7 | public class ConsoleInlineProgressBar : ConsoleProgressBar 8 | { 9 | public override void UpdateProgress(long done, long total) 10 | { 11 | if (Console.CursorLeft > 0) Console.WriteLine(); 12 | RememberColors(); 13 | //draw progress bar 14 | DrawProgressLine(done, total); 15 | RestoreColors(); 16 | } 17 | } -------------------------------------------------------------------------------- /WebTools/Models/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable MemberCanBePrivate.Global 2 | // ReSharper disable UnusedAutoPropertyAccessor.Global 3 | namespace aemarcoCommons.WebTools.Models; 4 | 5 | public class ErrorResponse 6 | { 7 | public ErrorResponse(int statusCode, string message) 8 | { 9 | StatusCode = statusCode; 10 | Message = message; 11 | } 12 | 13 | /// 14 | /// Http Status Code 15 | /// 16 | public int StatusCode { get; } 17 | 18 | /// 19 | /// some message 20 | /// 21 | public string Message { get; } 22 | } -------------------------------------------------------------------------------- /Tests/ExtensionsTests/CryptoExtensionsTests/HexStuffTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.CryptoExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | 5 | namespace ExtensionsTests.CryptoExtensionsTests; 6 | 7 | public class HexStuffTests 8 | { 9 | 10 | 11 | [TestCase("test", "098F6BCD4621D373CADE4E832627B4F6")] 12 | [TestCase("oMyDear", "77B80F6DE365762B070048D1F59ABB39")] 13 | public void ToHexHashString_Returns_Correctly(string text, string expected) 14 | { 15 | 16 | var result = text.ToHexHashString(); 17 | result.Should().Be(expected); 18 | } 19 | 20 | 21 | 22 | } -------------------------------------------------------------------------------- /WpfTools/Commands/DelegateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace aemarcoCommons.WpfTools.Commands; 5 | 6 | /// 7 | /// Simplistic delegate command . 8 | /// 9 | public class DelegateCommand : BaseCommand 10 | { 11 | public Func? CanExecuteFunc { get; set; } 12 | public override bool CanExecute(object? parameter) 13 | { 14 | return CanExecuteFunc == null || CanExecuteFunc(parameter); 15 | } 16 | 17 | public Action? CommandAction { get; set; } 18 | public override void Execute(object? parameter) 19 | { 20 | CommandAction?.Invoke(parameter); 21 | } 22 | } -------------------------------------------------------------------------------- /Tests/ToolboxAppOptionsTests/Configuration/ToolboxAppOptionsSettingsTests.cs: -------------------------------------------------------------------------------- 1 | namespace ToolboxAppOptionsTests.Configuration; 2 | 3 | public class ToolboxAppOptionsSettingsTests : AppOptionTestBase 4 | { 5 | 6 | [Test] 7 | public void HasExpectedDefaults() 8 | { 9 | var result = new ToolboxAppOptionsSettings(); 10 | 11 | result.StringTransformations.Should().HaveCount(0); 12 | result.Assemblies.Should().HaveCount(0); 13 | result.EnableValidationOnStartup.Should().Be(true); 14 | 15 | result.ConfigurationTypes.Should().HaveCount(0); 16 | result.ConfigurationAssemblies.Should().HaveCount(0); 17 | } 18 | } -------------------------------------------------------------------------------- /ToolboxFluentValidation/LICENSE.md: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 aemarco 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ -------------------------------------------------------------------------------- /ToolboxImage/LICENSE.md: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 aemarco 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /Extensions/TimeExtensions/TimingExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace aemarcoCommons.Extensions.TimeExtensions; 6 | 7 | public static class TimingExtensions 8 | { 9 | public static async Task WaitTill(this DateTimeOffset target, CancellationToken token) 10 | { 11 | if (target.IsFuture()) 12 | { 13 | var toWait = target - DateTimeOffset.Now; 14 | if (toWait.TotalMilliseconds > 0) 15 | { 16 | await Task.Delay(toWait, token) 17 | .ConfigureAwait(false); 18 | } 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | } -------------------------------------------------------------------------------- /WpfTools/Helpers/ProgressEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.WpfTools.Helpers; 4 | 5 | public class ProgressEventArgs : EventArgs 6 | { 7 | private readonly double? _percent; 8 | public ProgressEventArgs(double percent, int done, int total) 9 | { 10 | _percent = percent; 11 | Total = total; 12 | Done = done; 13 | } 14 | 15 | public ProgressEventArgs(int done, int total) 16 | { 17 | Done = done; 18 | Total = total; 19 | } 20 | public int Done { get; } 21 | public int Total { get; } 22 | 23 | public double Percent => _percent ?? Math.Max(0, Math.Min(100, 100.0 * Done / Total)); 24 | } -------------------------------------------------------------------------------- /ConsoleTools/BootstrapperExtensions.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Toolbox; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Spectre.Console.Cli; 4 | 5 | namespace aemarcoCommons.ConsoleTools; 6 | 7 | public static class BootstrapperExtensions 8 | { 9 | 10 | public static IServiceCollection SetupConsoleTools(this IServiceCollection services) 11 | { 12 | services.SetupToolbox(); 13 | 14 | 15 | 16 | return services; 17 | } 18 | 19 | //Microsoft.Extensions.DependencyInjection 20 | public static ITypeRegistrar ToTypeRegistrar(this IServiceCollection services) => 21 | new SpectreInfrastructure.ServiceCollectionTypeRegistrar(services); 22 | 23 | } -------------------------------------------------------------------------------- /Toolbox/CustomDatastructures/DropOutStack.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace aemarcoCommons.Toolbox.CustomDatastructures; 4 | 5 | public class DropOutStack 6 | { 7 | private readonly T[] _items; 8 | private int _top; 9 | public DropOutStack(int capacity) 10 | { 11 | _items = new T[capacity]; 12 | } 13 | 14 | public void Push(T item) 15 | { 16 | _items[_top] = item; 17 | _top = (_top + 1) % _items.Length; 18 | } 19 | public T Pop() 20 | { 21 | _top = (_items.Length + _top - 1) % _items.Length; 22 | return _items[_top]; 23 | } 24 | 25 | public bool Contains(T element) => _items.Contains(element); 26 | } -------------------------------------------------------------------------------- /WpfTools/BaseModels/BaseViewModelClose.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.Helpers; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | using CommunityToolkit.Mvvm.Input; 4 | using System; 5 | 6 | namespace aemarcoCommons.WpfTools.BaseModels; 7 | public partial class BaseViewModel : ICloseWindow 8 | { 9 | 10 | [ObservableProperty] 11 | [NotifyCanExecuteChangedFor(nameof(CloseCommand))] 12 | private Action? _closeAction; 13 | 14 | [RelayCommand(CanExecute = nameof(CanClose))] 15 | protected virtual void Close() 16 | { 17 | CloseAction?.Invoke(); 18 | } 19 | 20 | [ObservableProperty] 21 | private bool _canClose = true; 22 | 23 | } 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WebTools/Authorization/AllowedClients.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace aemarcoCommons.WebTools.Authorization; 4 | 5 | public static class AllowedClientsExtensions 6 | { 7 | public static IServiceCollection AddAllowedClientsPolicy( 8 | this IServiceCollection services, 9 | string policyName, 10 | params string[] clientIds) 11 | { 12 | services.AddAuthorization(config => 13 | { 14 | config.AddPolicy(policyName, builder => 15 | { 16 | builder 17 | .RequireClaim("client_id", clientIds); 18 | }); 19 | }); 20 | return services; 21 | } 22 | } -------------------------------------------------------------------------------- /WpfTools/Commands/BaseCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | 5 | namespace aemarcoCommons.WpfTools.Commands; 6 | 7 | public abstract class BaseCommand : ICommand 8 | { 9 | public event EventHandler? CanExecuteChanged 10 | { 11 | add => CommandManager.RequerySuggested += value; 12 | remove => CommandManager.RequerySuggested -= value; 13 | } 14 | public virtual void OnCanExecuteChanged() 15 | { 16 | CommandManager.InvalidateRequerySuggested(); 17 | } 18 | 19 | public virtual bool CanExecute(object? parameter) 20 | { 21 | return true; 22 | } 23 | 24 | public abstract void Execute(object? parameter); 25 | 26 | } -------------------------------------------------------------------------------- /Extensions/StorageExtensions/FileOpsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace aemarcoCommons.Extensions.StorageExtensions; 4 | 5 | public static class FileOpsExtensions 6 | { 7 | public static void MoveToFolder(this FileInfo file, string targetPath, bool overwrite = false) 8 | { 9 | file.CopyToFolder(targetPath, overwrite); 10 | File.Delete(file.FullName); 11 | } 12 | 13 | // ReSharper disable once MemberCanBePrivate.Global 14 | public static void CopyToFolder(this FileInfo file, string targetPath, bool overwrite = false) 15 | { 16 | var target = Path.Combine(targetPath, file.Name); 17 | File.Copy(file.FullName, target, overwrite); 18 | } 19 | } -------------------------------------------------------------------------------- /WpfTools/Dialogs/AskInputDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using CommunityToolkit.Mvvm.Input; 3 | 4 | namespace aemarcoCommons.WpfTools.Dialogs; 5 | public partial class AskInputDialogViewModel : DialogViewModel 6 | { 7 | 8 | public override string Title => "Question"; 9 | 10 | public AskInputDialogViewModel(string question) 11 | { 12 | Question = question; 13 | } 14 | // ReSharper disable once UnusedAutoPropertyAccessor.Global 15 | public string Question { get; } 16 | 17 | [ObservableProperty] 18 | private string _answer = string.Empty; 19 | 20 | [RelayCommand] 21 | private void Okay() 22 | { 23 | OnCloseDialog(true); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Tests/ExtensionsTests/NumberExtensionsTests/ComparisonExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.NumberExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | 5 | namespace ExtensionsTests.NumberExtensionsTests; 6 | 7 | public class ComparisonExtensionsTests 8 | { 9 | 10 | //[TestCase(5,5,0,true)] 11 | [TestCase(0.500001, 0.500002, 0.000001, true)] 12 | [TestCase(5.000001, 5.000002, 0.0000005, true)] 13 | [TestCase(5.000001, 5.000003, 0.0000001, false)] 14 | public void IsNearlyEqual_Rocks(double left, double right, double epsilon, bool expected) 15 | { 16 | var result = left.IsNearlyEqual(right, epsilon); 17 | result.Should().Be(expected); 18 | } 19 | 20 | 21 | 22 | 23 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.WindowStuff; 2 | using System.Windows; 3 | using WpfToolsManualTests.View; 4 | using WpfToolsManualTests.ViewModel; 5 | 6 | namespace WpfToolsManualTests; 7 | 8 | public partial class App 9 | { 10 | private void App_OnStartup(object sender, StartupEventArgs e) 11 | { 12 | IWindowService.RegisterView(); 13 | IWindowService.RegisterDialog(); 14 | 15 | var windowService = new WindowService(); 16 | 17 | MainWindow = new MainWindow() 18 | { 19 | DataContext = new MainWindowViewModel(windowService) 20 | }; 21 | MainWindow.Show(); 22 | } 23 | } -------------------------------------------------------------------------------- /WebTools/Cors/readme.md: -------------------------------------------------------------------------------- 1 | 2 | define cors policies in a static class 3 | public static class CorsOrigins 4 | { 5 | [CorsOrigin("https://example.com")] 6 | [CorsOrigin("https://example2.com")] 7 | [CorsMethod("post")] 8 | [CorsMethod("get")] 9 | [CorsPreflightMaxAge(1800)] 10 | public const string ExampleCom = "exampleCom"; 11 | } 12 | 13 | 14 | in Startup:ConfigureServices 15 | services.AddCors(options => options.AddCorsPolicies(typeof(CorsOrigins))); //register class in services 16 | 17 | 18 | in Startup:Configure 19 | app.UseRouting(); 20 | app.UseCors(); //check cors after route 21 | app.UseAuthentication(); 22 | 23 | 24 | Use in Controller as Attribute on Controller or Action 25 | [EnableCors(CorsOrigins.ExampleCom)] 26 | 27 | -------------------------------------------------------------------------------- /Extensions/VersionExtensions/VersionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace aemarcoCommons.Extensions.VersionExtensions; 5 | 6 | public static class VersionExtensions 7 | { 8 | 9 | [Obsolete("Will be removed in future versions")] 10 | public static void ToTextFile(this Version version, string filePath) 11 | { 12 | File.WriteAllText(filePath, version.ToString()); 13 | } 14 | 15 | 16 | [Obsolete("Will be removed in future versions")] 17 | public static Version ToVersionFromTextFile(this FileInfo file, string defaultVersion = "1.0.0.0") 18 | { 19 | return (file.Exists) 20 | ? Version.Parse(File.ReadAllText(file.FullName)) 21 | : Version.Parse(defaultVersion); 22 | } 23 | } -------------------------------------------------------------------------------- /Toolbox/NetworkTools/Internet.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.NetworkExtensions; 2 | using System.Net; 3 | using System.Threading.Tasks; 4 | 5 | namespace aemarcoCommons.Toolbox.NetworkTools; 6 | 7 | public static class Internet 8 | { 9 | /// 10 | /// Checks if the internet is accessible by pinging a default external host. 11 | /// 12 | /// The timeout in milliseconds for the ping operation. 13 | /// True if the internet is accessible; otherwise, false. 14 | public static async Task IsAccessible(int timeout = 3000) 15 | { 16 | var ip = IPAddress.Parse("8.8.8.8"); // Default to Google's DNS 17 | return await ip.IsPingable(timeout); 18 | } 19 | } -------------------------------------------------------------------------------- /Tests/ExtensionsTests/FileExtensionsTests/StorageSizeStuffTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.FileExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | 5 | namespace ExtensionsTests.FileExtensionsTests; 6 | 7 | public class StorageSizeStuffTests 8 | { 9 | 10 | 11 | 12 | 13 | //[Test, TestCaseSource("CovertCases")] 14 | [TestCase(1, "mb", "b", 1048576)] 15 | [TestCase(5, "kb", "b", 5120)] 16 | [TestCase(512, "kb", "mb", 0.5d)] 17 | [TestCase(2097152, "kb", "gb", 2)] 18 | [TestCase(1, "tb", "tb", 1)] 19 | public void ConvertFromTo_Converts_Correct(long val, string su, string tu, decimal expected) 20 | { 21 | var result = val.ConvertFromTo(su, tu); 22 | result.Should().Be(expected); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /Tests/ToolboxTopServiceManualTests/SampleService.cs: -------------------------------------------------------------------------------- 1 | namespace ToolboxTopServiceManualTests; 2 | 3 | internal static class SampleServiceExtensions 4 | { 5 | internal static HostApplicationBuilder SetupSampleService( 6 | this HostApplicationBuilder app) 7 | { 8 | app.Services.AddHostedService(); 9 | return app; 10 | } 11 | } 12 | 13 | internal class SampleService : BackgroundService 14 | { 15 | protected override async Task ExecuteAsync(CancellationToken stoppingToken) 16 | { 17 | while (!stoppingToken.IsCancellationRequested) 18 | { 19 | await Task.Delay(1000, stoppingToken); 20 | await Console.Out.WriteLineAsync("Hello from SampleService"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/ToolboxTests/BootstrapperExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Toolbox; 2 | using aemarcoCommons.Toolbox.Oidc; 3 | using FluentAssertions; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using NUnit.Framework; 6 | 7 | namespace ToolboxTests; 8 | public class BootstrapperExtensionsTests 9 | { 10 | 11 | [Test] 12 | public void SetupHttpClientStuff_RegistersResolvable_OidcTokenRenewalHandler() 13 | { 14 | var sp = new ServiceCollection() 15 | .SetupToolbox() 16 | .BuildServiceProvider(); 17 | 18 | var s = sp.GetService(); 19 | 20 | 21 | s.Should().NotBeNull(); 22 | 23 | } 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /ToolboxAppOptions/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using aemarcoCommons.Extensions; 2 | global using aemarcoCommons.ToolboxAppOptions.Services; 3 | global using aemarcoCommons.ToolboxAppOptions.Transformations; 4 | global using FluentValidation; 5 | global using Microsoft.Extensions.Configuration; 6 | global using Microsoft.Extensions.DependencyInjection; 7 | global using Microsoft.Extensions.Hosting; 8 | global using Microsoft.Extensions.Options; 9 | global using System; 10 | global using System.Collections; 11 | global using System.Collections.Generic; 12 | global using System.Linq; 13 | global using System.Reflection; 14 | global using System.Runtime.ExceptionServices; 15 | global using System.Text.RegularExpressions; 16 | global using System.Threading; 17 | global using System.Threading.Tasks; 18 | -------------------------------------------------------------------------------- /ToolboxAppOptions/Configuration/ToolboxAppOptionsSettings.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable once CheckNamespace 2 | namespace aemarcoCommons.ToolboxAppOptions; 3 | 4 | public record ToolboxAppOptionsSettings 5 | { 6 | public List StringTransformations { get; } = []; 7 | public List Assemblies { get; } = []; 8 | public bool EnableValidationOnStartup { get; internal set; } = true; 9 | 10 | 11 | /// 12 | /// resolved types implementing ISettingsBase 13 | /// 14 | internal IReadOnlyList ConfigurationTypes { get; set; } = []; 15 | /// 16 | /// assemblies containing ISettingsBase types 17 | /// 18 | internal IReadOnlyList ConfigurationAssemblies { get; set; } = []; 19 | } 20 | -------------------------------------------------------------------------------- /WpfTools/BaseNav/NavigationSetupService.cs: -------------------------------------------------------------------------------- 1 | 2 | using Microsoft.Extensions.Hosting; 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace aemarcoCommons.WpfTools.BaseNav; 8 | 9 | #pragma warning disable CsWinRT1028 10 | public class NavigationSetupService : BackgroundService 11 | #pragma warning restore CsWinRT1028 12 | { 13 | 14 | private readonly IServiceProvider _serviceProvider; 15 | public NavigationSetupService(IServiceProvider serviceProvider) 16 | { 17 | _serviceProvider = serviceProvider; 18 | } 19 | 20 | protected override Task ExecuteAsync(CancellationToken stoppingToken) 21 | { 22 | BaseNavWindowViewModel.ServiceProvider = _serviceProvider; 23 | return Task.CompletedTask; 24 | } 25 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/ViewModel/TestManualDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.Dialogs; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | using CommunityToolkit.Mvvm.Input; 4 | 5 | namespace WpfToolsManualTests.ViewModel; 6 | 7 | public partial class TestManualDialogViewModel : DialogViewModel 8 | { 9 | 10 | public override string Title => "Question"; 11 | 12 | public TestManualDialogViewModel(string question) 13 | { 14 | Question = question; 15 | } 16 | // ReSharper disable once UnusedAutoPropertyAccessor.Global 17 | public string Question { get; } 18 | 19 | [ObservableProperty] 20 | private string _answer = string.Empty; 21 | 22 | [RelayCommand] 23 | private void Okay() 24 | { 25 | OnCloseDialog(true); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /ToolboxConsole/CommandApp/ScTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using Spectre.Console.Cli; 2 | using System; 3 | 4 | namespace aemarcoCommons.ToolboxConsole.CommandApp; 5 | 6 | //https://spectreconsole.net/cli/commandapp 7 | //https://github.com/spectreconsole/examples/blob/main/examples/Cli/Injection/Infrastructure/TypeResolver.cs 8 | 9 | public sealed class ScTypeResolver : ITypeResolver, IDisposable 10 | { 11 | private readonly IServiceProvider _provider; 12 | public ScTypeResolver(IServiceProvider provider) => _provider = provider; 13 | 14 | public object? Resolve(Type? type) => 15 | type != null 16 | ? _provider.GetService(type) 17 | : null; 18 | 19 | public void Dispose() 20 | { 21 | if (_provider is IDisposable disposable) 22 | disposable.Dispose(); 23 | } 24 | } -------------------------------------------------------------------------------- /WpfTools/Extensions/CurrentCultureHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Markup; 4 | 5 | namespace aemarcoCommons.WpfTools.Extensions; 6 | 7 | //inspired by 8 | //https://youtu.be/6rrgoH6phvE 9 | 10 | public static class CurrentCultureHelper 11 | { 12 | 13 | public static void SetDefaults() 14 | { 15 | FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), 16 | new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name))); 17 | FrameworkElement.FlowDirectionProperty.OverrideMetadata(typeof(FrameworkElement), 18 | new FrameworkPropertyMetadata(CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft ? FlowDirection.RightToLeft : FlowDirection.LeftToRight)); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ToolboxImage/Contracts/IFixedImageInImage.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 aemarco 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace aemarcoCommons.ToolboxImage.Contracts; 18 | 19 | public interface IFixedImageInImage : IImageInImage 20 | { 21 | void SetImage(Image image); 22 | } -------------------------------------------------------------------------------- /WebTools/Exceptions/BadRequestException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.WebTools.Exceptions; 4 | 5 | public class BadRequestException : Exception 6 | { 7 | /// 8 | /// Exception based on Argument exception param name 9 | /// 10 | /// argument exception with param name 11 | public BadRequestException(ArgumentException exception) 12 | : base($"Reason ArgumentException '{exception.ParamName}'", exception) 13 | { 14 | 15 | } 16 | 17 | /// 18 | /// Exception based on general message, will be prefixed with Reason and put in '' 19 | /// 20 | /// parameter name or message 21 | public BadRequestException(string message) 22 | : base($"Reason '{message}'") 23 | { 24 | 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /WpfTools/Converters/Converters.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Extensions/Extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net8.0 6 | aemarcoCommons.Extensions 7 | aemarcoCommons.Extensions 8 | disable 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | frequently used c# extension methods 20 | Extensions 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Extensions/CryptoExtensions/HexStuff.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | 4 | namespace aemarcoCommons.Extensions.CryptoExtensions; 5 | 6 | public static class HexStuff 7 | { 8 | /// 9 | /// Hashes the text and x2 it to hex (results in 32 long string) 10 | /// 11 | /// text to hash 12 | /// hashed string as hex string 13 | public static string ToHexHashString(this string textToHash) 14 | { 15 | using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(textToHash))) 16 | { 17 | var hash = ms.ToHashBytes(); 18 | var sb = new StringBuilder(); 19 | foreach (var b in hash) 20 | { 21 | sb.Append(b.ToString("X2")); 22 | } 23 | return sb.ToString(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /WpfTools/Commands/ShowWindowCommand.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System; 4 | using System.Windows; 5 | 6 | namespace aemarcoCommons.WpfTools.Commands; 7 | 8 | public class ShowWindowCommand : DelegateCommand 9 | where T : IWindow 10 | { 11 | public ShowWindowCommand(IServiceProvider serviceProvider) 12 | { 13 | CommandAction = _ => 14 | { 15 | foreach (Window win in Application.Current.Windows) 16 | { 17 | if (win.GetType() == typeof(T)) 18 | { 19 | win.WindowState = WindowState.Normal; 20 | win.Activate(); 21 | return; 22 | } 23 | } 24 | serviceProvider.GetRequiredService().Show(); 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Toolbox/SortTools/NaturalSort.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Runtime.InteropServices; 4 | using System.Security; 5 | 6 | namespace aemarcoCommons.Toolbox.SortTools; 7 | 8 | [SuppressUnmanagedCodeSecurity] 9 | internal static class SafeNativeMethods 10 | { 11 | [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 12 | public static extern int StrCmpLogicalW(string psz1, string psz2); 13 | } 14 | 15 | public sealed class NaturalStringComparer : IComparer 16 | { 17 | public int Compare(string a, string b) 18 | { 19 | return SafeNativeMethods.StrCmpLogicalW(a, b); 20 | } 21 | } 22 | 23 | public sealed class NaturalFileInfoNameComparer : IComparer 24 | { 25 | public int Compare(FileInfo a, FileInfo b) 26 | { 27 | return SafeNativeMethods.StrCmpLogicalW(a?.Name, b?.Name); 28 | } 29 | } -------------------------------------------------------------------------------- /Toolbox/SerializationTools/JsonExtensions.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.FileExtensions; 2 | using Newtonsoft.Json; 3 | using System.IO; 4 | 5 | namespace aemarcoCommons.Toolbox.SerializationTools; 6 | 7 | public static class JsonExtensions 8 | { 9 | public static T StoreFromFile(this string filePath) 10 | where T : new() 11 | { 12 | if (!File.Exists(filePath)) return new T(); 13 | 14 | try 15 | { 16 | return JsonConvert.DeserializeObject(File.ReadAllText(filePath)); 17 | } 18 | catch 19 | { 20 | new FileInfo(filePath).TryDelete(); 21 | return new T(); 22 | } 23 | } 24 | 25 | public static void StoreToFile(this string filePath, object store) 26 | { 27 | File.WriteAllText(filePath, JsonConvert.SerializeObject(store, Formatting.Indented)); 28 | } 29 | } -------------------------------------------------------------------------------- /WpfTools/Helpers/MessageBoxHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace aemarcoCommons.WpfTools.Helpers; 4 | 5 | public static class MessageBoxHelper 6 | { 7 | //dissabled per default delivers default Result 8 | public static bool Enabled { get; set; } = false; 9 | 10 | 11 | 12 | public static string Text { get; set; } = "MyText"; 13 | public static string Title { get; set; } = "MyTitle"; 14 | public static MessageBoxButton Button { get; set; } = MessageBoxButton.OK; 15 | public static MessageBoxImage Image { get; set; } = MessageBoxImage.Information; 16 | public static MessageBoxResult Result { get; set; } = MessageBoxResult.OK; 17 | 18 | public static MessageBoxResult ShowMessageBox() 19 | { 20 | if (Enabled) 21 | Result = MessageBox.Show(Text, Title, Button, Image, Result); 22 | return Result; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /ConsoleTools/Interop/WindowVisibility.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System.Runtime.Versioning; 3 | 4 | namespace aemarcoCommons.ConsoleTools.Interop; 5 | 6 | internal static class WindowVisibility 7 | { 8 | private const int SwHide = 0; 9 | private const int SwShow = 5; 10 | 11 | [DllImport("kernel32.dll")] 12 | private static extern IntPtr GetConsoleWindow(); 13 | [DllImport("user32.dll")] 14 | private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 15 | 16 | 17 | [SupportedOSPlatform("windows")] 18 | internal static void Hide() 19 | { 20 | var handle = GetConsoleWindow(); 21 | ShowWindow(handle, SwHide); 22 | } 23 | 24 | [SupportedOSPlatform("windows")] 25 | internal static void Show() 26 | { 27 | var handle = GetConsoleWindow(); 28 | ShowWindow(handle, SwShow); 29 | } 30 | } -------------------------------------------------------------------------------- /WpfTools/Converters/Multiply.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace aemarcoCommons.WpfTools.Converters; 6 | 7 | public class Multiply : IValueConverter 8 | { 9 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 10 | { 11 | var format = new NumberFormatInfo { NumberDecimalSeparator = "." }; 12 | var result = 13 | double.TryParse(value?.ToString(), NumberStyles.Any, format, out var num1) && 14 | double.TryParse(parameter?.ToString(), NumberStyles.Any, format, out var num2) 15 | ? num1 * num2 16 | : 0; 17 | return result; 18 | } 19 | 20 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 21 | { 22 | throw new NotSupportedException(); 23 | } 24 | } -------------------------------------------------------------------------------- /ConsoleTools/SpectreInfrastructure/ServiceCollectionTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using Spectre.Console.Cli; 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace aemarcoCommons.ConsoleTools.SpectreInfrastructure; 5 | 6 | //https://spectreconsole.net/cli/commandapp 7 | //https://github.com/spectreconsole/examples/blob/main/examples/Cli/Injection/Infrastructure/TypeResolver.cs 8 | 9 | public sealed class ServiceCollectionTypeResolver : ITypeResolver, IDisposable 10 | { 11 | private readonly IServiceProvider _provider; 12 | public ServiceCollectionTypeResolver(IServiceProvider provider) => _provider = provider; 13 | 14 | public object? Resolve(Type? type) => 15 | type != null 16 | ? _provider.GetService(type) 17 | : null; 18 | 19 | public void Dispose() 20 | { 21 | if (_provider is IDisposable disposable) 22 | disposable.Dispose(); 23 | } 24 | } -------------------------------------------------------------------------------- /Extensions/TextExtensions/Parsing.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace aemarcoCommons.Extensions.TextExtensions; 4 | 5 | public static class Parsing 6 | { 7 | 8 | /// 9 | /// TryParse as string extension 10 | /// 11 | /// target struct type 12 | /// text to parse 13 | /// out the parsed value 14 | /// true if success 15 | public static bool TryParse(this string text, out T? value) 16 | where T : struct 17 | { 18 | var converter = TypeDescriptor.GetConverter(typeof(T)); 19 | try 20 | { 21 | value = (T?)converter.ConvertFromString(text); 22 | return true; 23 | } 24 | catch 25 | { 26 | value = null; 27 | return false; 28 | } 29 | } 30 | 31 | 32 | 33 | } -------------------------------------------------------------------------------- /WpfTools/Converters/ObjectToJson.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | 6 | namespace aemarcoCommons.WpfTools.Converters; 7 | 8 | /// 9 | /// Two-way converter from bool to Visibility // true means Visible 10 | /// 11 | [ValueConversion(typeof(object), typeof(string))] 12 | public class ObjectToJson : IValueConverter 13 | { 14 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 15 | { 16 | return value != null 17 | ? JsonConvert.SerializeObject(value, Formatting.Indented) 18 | : string.Empty; 19 | } 20 | 21 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 22 | { 23 | return value != null 24 | ? JsonConvert.DeserializeObject((string)value, targetType) 25 | : null; 26 | } 27 | } -------------------------------------------------------------------------------- /Extensions/TimeExtensions/CalculationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace aemarcoCommons.Extensions.TimeExtensions; 6 | 7 | public static class CalculationExtensions 8 | { 9 | public static TimeSpan Sum(this IEnumerable entries, Func selector) 10 | { 11 | return entries.Select(selector).Sum(); 12 | } 13 | public static TimeSpan Sum(this IEnumerable entries) 14 | { 15 | return entries.Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2); 16 | } 17 | 18 | 19 | 20 | public static int ToAgeYears(this DateTimeOffset value, DateTimeOffset? target = null) 21 | { 22 | target = target ?? DateTimeOffset.Now; 23 | 24 | int age = target.Value.Year - value.Year; 25 | if (value.AddYears(age) > target.Value) 26 | age--; 27 | return age; 28 | } 29 | 30 | 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /WpfTools/Dialogs/DialogWindow.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | 20 | -------------------------------------------------------------------------------- /ToolboxAppOptions/Services/AppOptionsTransformationService.cs: -------------------------------------------------------------------------------- 1 | namespace aemarcoCommons.ToolboxAppOptions.Services; 2 | 3 | public class AppOptionsTransformationService 4 | { 5 | 6 | private readonly ToolboxAppOptionsSettings _options; 7 | private readonly IConfigurationRoot _config; 8 | public AppOptionsTransformationService( 9 | ToolboxAppOptionsSettings options, 10 | IConfigurationRoot config) 11 | { 12 | _options = options; 13 | _config = config; 14 | } 15 | 16 | 17 | public void PerformWriteTransformation(ISettingsBase options) 18 | { 19 | var transformations = _options.StringTransformations.ToList(); 20 | transformations.Reverse(); 21 | 22 | //ApplyReadTransformations 23 | foreach (var transformation in transformations) 24 | StringTransformerBase.TransformObject(options, _config, transformation.PerformWriteTransformation); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Tests/ToolboxAppOptionsTests/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "ShowCase": { 4 | "Hidden": "awesome", 5 | "Message": "{{{Hidden}}}" 6 | }, 7 | 8 | 9 | 10 | "TestSettings": { 11 | "Message": "HelloWorld" 12 | }, 13 | 14 | 15 | "Message": "root", 16 | "ClassSettings": { 17 | "Message": "class" 18 | }, 19 | "NestedA": { 20 | "NestedB": { 21 | "Message": "nested" 22 | } 23 | }, 24 | "PlaceholderTestSettings": { 25 | "PlaceholderValue": "Bob", 26 | "Message": "{{{PlaceholderValue}}}" 27 | }, 28 | "ProtectedTestSettings": { 29 | "Message": "Nj4KRDlw1axXf05Kv1dHXk3C3G91VaQVN+Xxt7MJjBMCwNqAsxVgJj/5Im/VbNPB3A==" 30 | }, 31 | 32 | 33 | 34 | 35 | "ValidationPassTestSettings": { 36 | "Message": "Validated" 37 | }, 38 | 39 | "ValidationFailTestSettings": { 40 | "Message": "" 41 | }, 42 | 43 | 44 | "SingleValidationTestSettings": { 45 | "Message": "StillHelloWorld" 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /ConsoleTools/Interop/PowerShellHelper.cs: -------------------------------------------------------------------------------- 1 | using CliWrap; 2 | using System.Threading.Tasks; 3 | 4 | namespace aemarcoCommons.ConsoleTools.Interop; 5 | 6 | public static class PowerShellHelper 7 | { 8 | public static async Task RunCommand( 9 | string command, 10 | params string[] args) 11 | { 12 | try 13 | { 14 | var cmd = Toolbox.ShellTools.PowerShellHelper.CreateCommand(command, args) 15 | .WithStandardOutputPipe(PipeTarget.ToDelegate(x => AnsiConsole.MarkupLine("[grey50]{0}[/]", x.EscapeMarkup()))); 16 | AnsiConsole.MarkupLine("[green]{0}[/]", $"Starting {cmd}".EscapeMarkup()); 17 | var result = await cmd.ExecuteAsync(); 18 | 19 | AnsiConsole.MarkupLine($"[green]Success[/] ({result.RunTime.TotalSeconds:N2} sec.)"); 20 | } 21 | catch (Exception ex) 22 | { 23 | AnsiConsole.WriteException(ex); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /WpfTools/Converters/BoolToVisibilityInvers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace aemarcoCommons.WpfTools.Converters; 7 | 8 | /// 9 | /// Two-way converter from bool to Visibility // false means visible 10 | /// 11 | [ValueConversion(typeof(bool), typeof(Visibility))] 12 | public class BoolToVisibilityInvers : IValueConverter 13 | { 14 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 15 | { 16 | return value is true 17 | ? Visibility.Collapsed 18 | : Visibility.Visible; 19 | } 20 | 21 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 22 | { 23 | if (value is string strValue && Enum.TryParse(strValue, out Visibility result)) 24 | { 25 | return result; 26 | } 27 | return DependencyProperty.UnsetValue; 28 | } 29 | } -------------------------------------------------------------------------------- /WpfTools/Extensions/ImageExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing.Imaging; 2 | using System.IO; 3 | using System.Windows.Media; 4 | 5 | namespace aemarcoCommons.WpfTools.Extensions; 6 | 7 | public static class ImageExtensions 8 | { 9 | public static ImageSource? ToImageSource(this System.Drawing.Image? image) 10 | { 11 | if (image == null) 12 | return null; 13 | 14 | var memoryStream = new MemoryStream(); 15 | image.Save(memoryStream, ImageFormat.Jpeg); 16 | memoryStream.Seek(0, SeekOrigin.Begin); 17 | var result = memoryStream.ToImageSource(); 18 | return result; 19 | } 20 | public static ImageSource? ToImageSource(this Stream? image) 21 | { 22 | if (image == null) 23 | return null; 24 | 25 | var bitmap = new System.Windows.Media.Imaging.BitmapImage(); 26 | bitmap.BeginInit(); 27 | bitmap.StreamSource = image; 28 | bitmap.EndInit(); 29 | return bitmap; 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /WpfTools/Converters/IntToString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace aemarcoCommons.WpfTools.Converters; 7 | 8 | /// 9 | /// Two-way converter from int to string 10 | /// 11 | [ValueConversion(typeof(int), typeof(string))] 12 | public class IntToString : IValueConverter 13 | { 14 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 15 | { 16 | if (value == null) 17 | throw new ArgumentNullException(nameof(value)); 18 | 19 | int intType = (int)value; 20 | return intType.ToString(); 21 | } 22 | 23 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 24 | { 25 | string? strValue = value as string; 26 | if (int.TryParse(strValue, out int resultInt)) 27 | { 28 | return resultInt; 29 | } 30 | return DependencyProperty.UnsetValue; 31 | } 32 | } -------------------------------------------------------------------------------- /ToolboxFluentValidation/NOTICE.md: -------------------------------------------------------------------------------- 1 | aemarcoToolboxFluentValidation uses third-party libraries or other resources that may be 2 | distributed under licenses different than aemarcoToolboxFluentValidation itself. 3 | 4 | In the event that we accidentally failed to list a required notice, please 5 | bring it to our attention by posting an issue. 6 | 7 | The attached notices are provided for information only. 8 | 9 | --- 10 | 11 | **License Notice for FluentValidation** 12 | FluentValidation is a library licensed under the **Apache License 2.0**. 13 | For more information, see: https://github.com/FluentValidation/FluentValidation 14 | 15 | --- 16 | 17 | **CronExpressionDescriptor** 18 | CronExpressionDescriptor is a library licensed under the **MIT License**. 19 | For more information, see: https://github.com/bradymholt/cron-expression-descriptor 20 | 21 | --- 22 | 23 | This NOTICE file is provided for information purposes only and includes important licensing details required for the third-party components referenced by aemarcoToolboxFluentValidation. 24 | -------------------------------------------------------------------------------- /WpfTools/Commands/AsyncDelegateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Input; 4 | 5 | 6 | namespace aemarcoCommons.WpfTools.Commands; 7 | 8 | public class AsyncDelegateCommand : ICommand 9 | { 10 | 11 | public event EventHandler? CanExecuteChanged 12 | { 13 | add => CommandManager.RequerySuggested += value; 14 | remove => CommandManager.RequerySuggested -= value; 15 | } 16 | protected virtual void OnCanExecuteChanged() 17 | { 18 | CommandManager.InvalidateRequerySuggested(); 19 | } 20 | 21 | 22 | 23 | public Func? CanExecuteFunc { get; init; } 24 | public bool CanExecute(object? parameter) 25 | { 26 | return CanExecuteFunc is null || CanExecuteFunc(parameter); 27 | } 28 | 29 | 30 | public Func? CommandAction { get; init; } 31 | public async void Execute(object? parameter) 32 | { 33 | if (CommandAction is not null) 34 | await CommandAction(parameter); 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /Extensions/NetworkExtensions/IpAddressExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.NetworkInformation; 3 | using System.Threading.Tasks; 4 | 5 | namespace aemarcoCommons.Extensions.NetworkExtensions; 6 | 7 | public static class IpAddressExtensions 8 | { 9 | /// 10 | /// Checks if a specified Ip is reachable via ping. 11 | /// 12 | /// The IP address to ping 13 | /// The timeout in milliseconds for the ping operation. 14 | /// True if the host is reachable; otherwise, false. 15 | public static async Task IsPingable(this IPAddress ip, int timeout = 3000) 16 | { 17 | try 18 | { 19 | using (Ping ping = new Ping()) 20 | { 21 | PingReply reply = await ping.SendPingAsync(ip, timeout); 22 | return reply.Status == IPStatus.Success; 23 | } 24 | } 25 | catch 26 | { 27 | return false; 28 | } 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /WpfTools/Converters/BoolToVisibility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows; 4 | using System.Windows.Data; 5 | 6 | namespace aemarcoCommons.WpfTools.Converters; 7 | 8 | /// 9 | /// Two-way converter from bool to Visibility // true means Visible 10 | /// 11 | [ValueConversion(typeof(bool), typeof(Visibility))] 12 | public class BoolToVisibility : IValueConverter 13 | { 14 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 15 | { 16 | if (value is not null && (bool)value) 17 | return Visibility.Visible; 18 | else 19 | return Visibility.Collapsed; 20 | } 21 | 22 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 23 | { 24 | string? strValue = value as string; 25 | if (Enum.TryParse(strValue, out Visibility result)) 26 | { 27 | return result; 28 | } 29 | return DependencyProperty.UnsetValue; 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/ExtensionsTests/ExtensionsTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net9.0 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ToolboxTopService/ToolboxTopService.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net8.0-windows 6 | 7 | aemarcoCommons.ToolboxTopService 8 | aemarcoCommons.ToolboxTopService 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Tool for installing a Windows service 20 | WindowsService Topshelf 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ConsoleTools/Power/Input/Decision.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | // ReSharper disable once CheckNamespace 4 | namespace aemarcoCommons.ConsoleTools; 5 | 6 | public static partial class PowerConsole 7 | { 8 | /// /// 9 | /// Gets a Yes/No decision through a ConsoleMenu selection 10 | /// 11 | /// /// question to ask 12 | /// /// clear console before asking 13 | /// true if decision is Yes 14 | public static bool EnsureDecision(string question, bool clear = true) 15 | { 16 | if (clear) 17 | Console.Clear(); 18 | 19 | static string GetText(bool x) => x ? "Yes" : "No"; 20 | var result = AnsiConsole.Prompt( 21 | new SelectionPrompt() 22 | .Title($"[purple]{question}[/]") 23 | .UseConverter(GetText) 24 | .AddChoices([true, false])); 25 | AnsiConsole.MarkupLine($"[purple]{question}[/] [green]{GetText(result)}[/]"); 26 | 27 | 28 | return result; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aemarcoCommons [![Build Status](https://dev.azure.com/aemarco/aemarcoCommons/_apis/build/status/aemarco.aemarcoCommons?branchName=master)](https://dev.azure.com/aemarco/aemarcoCommons/_build/latest?definitionId=10&branchName=master) 2 | 3 | Some Extensions, some Toolbox, some Console-, Wpf- and Web-Tools 4 | 5 | ## Donating? 6 | If you want to show some love, ETH donations are very welcome @ 0x95378259e5140Fe6D78811790A679AC6b9554866 7 | 8 | ## Packages 9 | 10 | 1. [WpfTools](https://github.com/aemarco/aemarcoCommons/tree/master/WpfTools) 11 | 1. [ConsoleTools](https://github.com/aemarco/aemarcoCommons/tree/master/ConsoleTools) 12 | 1. [WebTools](https://github.com/aemarco/aemarcoCommons/tree/master/WebTools) 13 | 1. [ToolboxAppOptions](https://github.com/aemarco/aemarcoCommons/tree/master/ToolboxAppOptions) 14 | 1. [ToolboxTopService](https://github.com/aemarco/aemarcoCommons/tree/master/ToolboxTopService) 15 | 1. [Toolbox](https://github.com/aemarco/aemarcoCommons/tree/master/Toolbox) 16 | 1. [Extensions](https://github.com/aemarco/aemarcoCommons/tree/master/Extensions) 17 | -------------------------------------------------------------------------------- /WpfTools/Helpers/ProgressHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.WpfTools.Helpers; 4 | 5 | public class ProgressHelper 6 | { 7 | private int _countDone; 8 | readonly int _countTotal; 9 | readonly EventHandler? _progress; 10 | private readonly EventHandler? _completed; 11 | readonly object _caller; 12 | 13 | public ProgressHelper(int countTotal, EventHandler? progress, EventHandler? completed, object caller) 14 | { 15 | _countDone = 0; 16 | _countTotal = countTotal; 17 | _progress = progress; 18 | _completed = completed; 19 | _caller = caller; 20 | } 21 | 22 | public void ReportProgress() 23 | { 24 | _countDone++; 25 | var progress = 100.0 * _countDone / _countTotal; 26 | 27 | _progress?.Invoke(_caller, new ProgressEventArgs(progress, _countDone, _countTotal)); 28 | 29 | if (_countDone == _countTotal) 30 | { 31 | _completed?.Invoke(_caller, EventArgs.Empty); 32 | } 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /WpfTools/Converters/TimespanToString.cs: -------------------------------------------------------------------------------- 1 | using Humanizer; 2 | using Humanizer.Localisation; 3 | using System; 4 | using System.Globalization; 5 | using System.Windows.Data; 6 | 7 | 8 | namespace aemarcoCommons.WpfTools.Converters; 9 | 10 | [ValueConversion(typeof(TimeSpan?), typeof(string))] 11 | public class TimespanToString : IValueConverter 12 | { 13 | /// 14 | /// One-way converter from TimeSpan? to string 15 | /// 16 | 17 | 18 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 19 | { 20 | var val = (TimeSpan?)value; 21 | 22 | if (!val.HasValue) 23 | return "Unknown"; 24 | 25 | var human = val.Value.Humanize(2, collectionSeparator: " ", minUnit: TimeUnit.Second); 26 | return val.Value.TotalMilliseconds < 0 27 | ? $"- {human}" 28 | : human; 29 | } 30 | 31 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 32 | { 33 | throw new NotSupportedException(); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /aemarcoCommons.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True 6 | True 7 | True 8 | True 9 | True -------------------------------------------------------------------------------- /Extensions/NumberExtensions/ComparisonExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace aemarcoCommons.Extensions.NumberExtensions; 4 | 5 | public static class ComparisonExtensions 6 | { 7 | 8 | public static bool IsNearlyEqual(this double number, double compareValue, double epsilon = 0.0000001d) 9 | { 10 | const double minNormal = 2.2250738585072014E-308d; 11 | var absA = Math.Abs(number); 12 | var absB = Math.Abs(compareValue); 13 | var diff = Math.Abs(number - compareValue); 14 | 15 | if (number.Equals(compareValue)) 16 | { // shortcut, handles infinities 17 | return true; 18 | } 19 | else if (number.Equals(0) || compareValue.Equals(0) || absA + absB < minNormal) 20 | { 21 | // a or b is zero or both are extremely close to it 22 | // relative error is less meaningful here 23 | return diff < (epsilon * minNormal); 24 | } 25 | else 26 | { // use relative error 27 | return diff / (absA + absB) < epsilon; 28 | } 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /ConsoleTools/ConsoleTools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net8.0 6 | aemarcoCommons.ConsoleTools 7 | aemarcoCommons.ConsoleTools 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | c# console tools collection 25 | ConsoleTools 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /WpfTools/BaseModels/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.NetworkExtensions; 2 | using CommunityToolkit.Mvvm.Input; 3 | using System; 4 | using System.Windows; 5 | 6 | namespace aemarcoCommons.WpfTools.BaseModels; 7 | 8 | // ReSharper disable once PartialTypeWithSinglePart 9 | public partial class BaseViewModel : BaseNotifier, IBaseViewModel 10 | { 11 | [RelayCommand(CanExecute = nameof(CanNavigateToUrl))] 12 | // ReSharper disable once UnusedMember.Local 13 | protected virtual void NavigateToUrl(string url) 14 | { 15 | if (string.IsNullOrWhiteSpace(url)) 16 | throw new Exception("Must provide a url"); 17 | new Uri(url).OpenInBrowser(); 18 | } 19 | 20 | protected virtual bool CanNavigateToUrl(string url) 21 | { 22 | return !string.IsNullOrWhiteSpace(url) && 23 | Uri.TryCreate(url, UriKind.Absolute, out _); 24 | } 25 | 26 | public bool True => true; 27 | public bool False => false; 28 | 29 | 30 | [RelayCommand] 31 | protected virtual void ExitApplication() 32 | => Application.Current.Shutdown(); 33 | 34 | } -------------------------------------------------------------------------------- /ConsoleTools/Power/Shutdown/CancelKeyPressHandler.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Threading; 3 | 4 | //namespace aemarcoCommons.ConsoleTools.Power.Shutdown; 5 | //public class CancelKeyPressHandler 6 | //{ 7 | 8 | 9 | // private readonly CancellationTokenSource _cancellationTokenSource; 10 | 11 | // public CancelKeyPressHandler() 12 | // { 13 | // _cancellationTokenSource = new CancellationTokenSource(); 14 | 15 | // } 16 | 17 | // private CancellationToken GetCancellationToken() 18 | // { 19 | // Console.CancelKeyPress += Console_CancelKeyPress; 20 | // return _cancellationTokenSource.Token; 21 | // } 22 | 23 | // private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) 24 | // { 25 | // Console.WriteLine(); 26 | // Console.WriteLine("Canceling..."); 27 | // _cancellationTokenSource.Cancel(); 28 | // e.Cancel = true; 29 | // } 30 | 31 | 32 | // public static explicit operator CancellationToken(CancelKeyPressHandler handler) 33 | // { 34 | // return handler.GetCancellationToken(); 35 | // } 36 | 37 | //} 38 | -------------------------------------------------------------------------------- /ToolboxTopService/README.md: -------------------------------------------------------------------------------- 1 | # `aemarcoToolboxTopService` 2 | 3 |
4 | 5 | ## Overview 6 | This package injects some commands into the Application, to make it easier to use. 7 | The behaviour of it is somewhat inspired by "Topshelf". 8 | 9 | - HostedService as WindowsService 10 | - Use Commands directly on the app (see Commands section) 11 | 12 | ## Get Started 13 | ``` 14 | { 15 | HostApplicationBuilder app = Host.CreateApplicationBuilder(args); 16 | app.Services.AddHostedService(); 17 | await app.RunAsTopService(x => x 18 | .ServiceName("SomeService") 19 | .DisplayName("Some Service") 20 | .Description("SampleService installed with TopService")); 21 | } 22 | ``` 23 | 24 | ## Commands 25 | - "install" to install as a windows service 26 | - "uninstall" to uninstall the service 27 | - "start" to start the service 28 | - "stop" to stop the service 29 | 30 | ## Startup Type 31 | ``` 32 | { 33 | x.StartupType(StartupType.AutoDelayed)); 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /WpfTools/BaseNav/ViewStuff.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | 3 | namespace aemarcoCommons.WpfTools.BaseNav; 4 | 5 | //user controls 6 | public interface INavView //inherit in specific interface for view 7 | { 8 | object DataContext { get; set; } 9 | 10 | } 11 | 12 | //view models 13 | public interface INavViewModel : IBaseViewModel //inherit in specific interface for view model, inherit from BaseNaveViewModel 14 | { 15 | BaseNavWindowViewModel WindowViewModel { get; set; } 16 | INavView View { get; set; } 17 | string? Title { get; } 18 | } 19 | 20 | 21 | 22 | 23 | public abstract class BaseNavViewModel : BaseViewModel, INavViewModel 24 | { 25 | protected BaseNavViewModel( 26 | INavView view) 27 | { 28 | View = view; 29 | View.DataContext = this; 30 | } 31 | 32 | 33 | public INavView View { get; set; } 34 | 35 | 36 | public BaseNavWindowViewModel WindowViewModel { get; set; } = null!; 37 | 38 | public virtual string? Title => null; 39 | 40 | 41 | protected override void Close() 42 | { 43 | WindowViewModel.Window.Close(); 44 | } 45 | } -------------------------------------------------------------------------------- /WpfTools/WindowStuff/IWindowService.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.BaseModels; 2 | using aemarcoCommons.WpfTools.Dialogs; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Windows; 6 | using System.Windows.Controls; 7 | 8 | namespace aemarcoCommons.WpfTools.WindowStuff; 9 | 10 | //inspired by 11 | //https://youtu.be/S8hEjLahNtU 12 | 13 | public interface IWindowService 14 | { 15 | 16 | void Show() where TViewModel : BaseViewModel; 17 | 18 | bool? ShowDialog(DialogViewModel viewModel); 19 | bool? ShowDialog() where TViewModel : DialogViewModel; 20 | 21 | 22 | 23 | static readonly Dictionary Mappings = []; 24 | static void RegisterView() 25 | where TWindow : Window, new() 26 | where TViewModel : BaseViewModel 27 | { 28 | Mappings[typeof(TViewModel)] = typeof(TWindow); 29 | } 30 | static void RegisterDialog() 31 | where TView : UserControl, new() 32 | where TViewModel : DialogViewModel 33 | { 34 | Mappings.Add(typeof(TViewModel), typeof(TView)); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /Tests/WpfToolsTests/WpfToolsTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net9.0-windows10.0.19041.0 6 | 10.0 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ToolboxConsole/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 aemarco 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/ViewModel/MainWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.WpfTools.WindowStuff; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | using CommunityToolkit.Mvvm.Input; 4 | using System.Windows; 5 | 6 | namespace WpfToolsManualTests.ViewModel; 7 | 8 | public partial class MainWindowViewModel : ObservableObject 9 | { 10 | 11 | private readonly IWindowService _windowService; 12 | public MainWindowViewModel( 13 | IWindowService windowService) 14 | { 15 | _windowService = windowService; 16 | } 17 | 18 | [RelayCommand] 19 | private void Submit() 20 | { 21 | MessageBox.Show("Clicked"); 22 | } 23 | 24 | 25 | [RelayCommand] 26 | private void Window() 27 | { 28 | _windowService.Show(); 29 | } 30 | 31 | [RelayCommand] 32 | private void Dialog() 33 | { 34 | var question = new TestManualDialogViewModel("What is the answer?"); 35 | var dialogResult = _windowService.ShowDialog(question); 36 | if (dialogResult is true) 37 | { 38 | MessageBox.Show($"Answer is {question.Answer}"); 39 | } 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /Tests/ExtensionsTests/TimeExtensionsTests/ComparisonExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using aemarcoCommons.Extensions.TimeExtensions; 2 | using FluentAssertions; 3 | using NUnit.Framework; 4 | using System; 5 | 6 | namespace ExtensionsTests.TimeExtensionsTests; 7 | 8 | public class ComparisonExtensionsTests 9 | { 10 | 11 | [TestCase(5, 6, true)] 12 | [TestCase(5, 4, false)] 13 | public void IsYoungerThan_ReturnsCorrect(int hoursInPast, int hoursInterval, bool expected) 14 | { 15 | var timestamp = DateTimeOffset.Now.AddHours(-hoursInPast); 16 | var timespan = TimeSpan.FromHours(hoursInterval); 17 | 18 | var result = timestamp.IsYoungerThan(timespan); 19 | 20 | result.Should().Be(expected); 21 | } 22 | 23 | 24 | [TestCase(5, 6, false)] 25 | [TestCase(5, 4, true)] 26 | public void IsOlderThan_ReturnsCorrect(int hoursInPast, int hoursInterval, bool expected) 27 | { 28 | var timestamp = DateTimeOffset.Now.AddHours(-hoursInPast); 29 | var timespan = TimeSpan.FromHours(hoursInterval); 30 | 31 | var result = timestamp.IsOlderThan(timespan); 32 | 33 | result.Should().Be(expected); 34 | } 35 | } -------------------------------------------------------------------------------- /ToolboxImage/Contracts/IImageInImage.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 aemarco 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace aemarcoCommons.ToolboxImage.Contracts; 18 | 19 | public interface IImageInImage : IDisposable 20 | { 21 | Rectangle TargetArea { get; } 22 | 23 | Image Image { get; } 24 | DateTimeOffset Timestamp { get; } 25 | bool ChangedSinceDrawn { get; } 26 | 27 | public void SetImage( 28 | Image image, 29 | ImageScaleMode mode, 30 | int maxHorizontalCropPercentage, 31 | int maxVerticalCropPercentage); 32 | 33 | void DrawToImage(Image image); 34 | } -------------------------------------------------------------------------------- /WebTools/Extensions/ContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.Net.Http.Headers; 3 | // ReSharper disable MemberCanBePrivate.Global 4 | // ReSharper disable UnusedMember.Global 5 | 6 | namespace aemarcoCommons.WebTools.Extensions; 7 | 8 | public static class ContextExtensions 9 | { 10 | public static string GetRootPath(this HttpContext context) 11 | { 12 | var uri = $"{context.Request.Scheme}://{context.Request.Host.ToUriComponent()}"; 13 | return uri; 14 | } 15 | 16 | public static string GetBasePath(this HttpContext context) 17 | { 18 | var uri = $"{context.GetRootPath()}{context.Request.PathBase.ToUriComponent()}"; 19 | return uri; 20 | } 21 | 22 | public static string GetAbsolutePath(this HttpContext context) 23 | { 24 | var uri = $"{context.GetBasePath()}{context.Request.Path.ToUriComponent()}{context.Request.QueryString.ToUriComponent()}"; 25 | return uri; 26 | } 27 | 28 | public static string GetAccessToken(this HttpContext context) 29 | { 30 | var token = context.Request.Headers[HeaderNames.Authorization].ToString(); 31 | return token; 32 | } 33 | } -------------------------------------------------------------------------------- /Tests/WpfToolsManualTests/View/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 |