JustArchiNET.Madness 3.10.0

.NET Standard 2.0
dotnet add package JustArchiNET.Madness --version 3.10.0
NuGet\Install-Package JustArchiNET.Madness -Version 3.10.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="JustArchiNET.Madness" Version="3.10.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add JustArchiNET.Madness --version 3.10.0
#r "nuget: JustArchiNET.Madness, 3.10.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install JustArchiNET.Madness as a Cake Addin
#addin nuget:?package=JustArchiNET.Madness&version=3.10.0

// Install JustArchiNET.Madness as a Cake Tool
#tool nuget:?package=JustArchiNET.Madness&version=3.10.0

☠️ Madness

Build status (GitHub) Github last commit date NuGet Total downloads License

GitHub stable release version NuGet stable release version GitHub stable release date

GitHub experimental release version NuGet experimental release version GitHub experimental release date

GitHub sponsor Crypto donate PayPal.me donate PayPal donate Revolut donate Steam donate


Repobeats analytics image


Description

Madness embraces your project by including compatibility layer for selected APIs normally not available on .NET Framework (and alike) platforms.

Installation

We support netstandard2.0, so .NET Framework 4.6.1 and newer. There is also a netstandard2.1 package that can be used e.g. on Xamarin.

dotnet add package JustArchiNET.Madness

If you're targetting multiple frameworks out of which only one is .NET Framework (e.g. net5.0 and net48), it's usually a good idea to not pull it for the others.

<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
	<PackageReference Include="JustArchiNET.Madness" />
</ItemGroup>

Usage

Usage depends on where you need to go mad. It'll require from you to add appropriate using clause in the affected source files.

Hint

Instead of adding using clause to each file, you can instead decide to do it once in the csproj (or appropriate project declaration) file. This way you won't need to add #if NETFRAMEWORK only for using JustArchiNET.Madness(...) clauses.

Example:

<ItemGroup Condition="'$(TargetFramework)' == 'net48'">
	<PackageReference Include="JustArchiNET.Madness" />

	<Using Include="JustArchiNET.Madness" />
	<Using Include="JustArchiNET.Madness.ArgumentNullExceptionMadness.ArgumentNullException" Alias="ArgumentNullException" />
	<Using Include="JustArchiNET.Madness.ArrayMadness.Array" Alias="Array" />
	<Using Include="JustArchiNET.Madness.ConvertMadness.Convert" Alias="Convert" />
	<Using Include="JustArchiNET.Madness.EnumMadness.Enum" Alias="Enum" />
	<Using Include="JustArchiNET.Madness.EnvironmentMadness.Environment" Alias="Environment" />
	<Using Include="JustArchiNET.Madness.FileMadness.File" Alias="File" />
	<Using Include="JustArchiNET.Madness.HashCodeMadness.HashCode" Alias="HashCode" />
	<Using Include="JustArchiNET.Madness.HMACSHA1Madness.HMACSHA1" Alias="HMACSHA1" />
	<Using Include="JustArchiNET.Madness.HttpRequestExceptionMadness.HttpRequestException" Alias="HttpRequestException" />
	<Using Include="JustArchiNET.Madness.OperatingSystemMadness.OperatingSystem" Alias="OperatingSystem" />
	<Using Include="JustArchiNET.Madness.PathMadness.Path" Alias="Path" />
	<Using Include="JustArchiNET.Madness.QuicExceptionMadness.QuicException" Alias="QuicException" />
	<Using Include="JustArchiNET.Madness.RandomMadness.Random" Alias="Random" />
	<Using Include="JustArchiNET.Madness.SHA256Madness.SHA256" Alias="SHA256" />
	<Using Include="JustArchiNET.Madness.SHA512Madness.SHA512" Alias="SHA512" />
	<Using Include="JustArchiNET.Madness.StringMadness.String" Alias="String" />
</ItemGroup>

We recommend to add <Using> clauses only for parts that you actually require/want to use from Madness.

Because of the File using declared above, you're now able to write this very nice ifdef-free code for both net48 and newer platform target:

using System.IO;
using System.Threading.Tasks;

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static async Task Scream() {
			// This compiles for both .NET Framework and other targets without any #if clauses, nice
			await File.WriteAllTextAsync("example.txt", "example").ConfigureAwait(false);
		}
	}
}

Static extensions

Static extensions include useful stuff that you'll usually stumble upon with newer language syntax and/or .NET platform.

Examples include native deconstruction (for all types), DisposeAsync() as well as support for await using { } blocks, or methods working with ReadOnlyMemory.

#if NETFRAMEWORK
using JustArchiNET.Madness;
#endif
using System.IO;
using System.Threading.Tasks;

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static async Task Scream() {
			MemoryStream stream = new MemoryStream();

			// Wow, this compiles now, but .NET Framework can't into `IAsyncDisposable`!
			// HOW IS THIS POSSIBLE, THIS IS MADNESS ☠️
			await stream.DisposeAsync().ConfigureAwait(false);
		}
	}
}

IndexRange

This library includes a dependency on awesome IndexRange project, which allows you to use System.Index and System.Range on .NET Framework.

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static void Scream() {
			const string text = "Madness?";

			string? subString = text[1..^1];
		}
	}
}

Check IndexRange project for more details.

File extensions

File extensions include mostly Async overloads for selected methods.

#if NETFRAMEWORK
using File = JustArchiNET.Madness.FileMadness.File;
#else
using System.IO;
#endif
using System.Threading.Tasks;

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static async Task Scream() {
			// This compiles for both .NET Framework and other targets without more #if clauses, nice
			await File.WriteAllTextAsync("example.txt", "example").ConfigureAwait(false);
		}
	}
}

HashCode extensions

HashCode extensions include implementation of Combine<T1, T2...>().

#if NETFRAMEWORK
using HashCode = JustArchiNET.Madness.HashCodeMadness.HashCode;
#else
using System;
#endif

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static void Scream() {
			int example = HashCode.Combine("test", "test2", "test3");
		}
	}
}

Path extensions

Path extensions include fully backported implementation of Path.GetRelativePath(), including more complex scenarios than below.

#if NETFRAMEWORK
using Path = JustArchiNET.Madness.PathMadness.Path;
#else
using System.IO;
#endif

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static void Scream() {
			// This compiles for both .NET Framework and other targets without more #if clauses, nice
			string example = Path.GetRelativePath("/tmp", "/tmp/example/example.txt");
		}
	}
}

OperatingSystem extensions

OperatingSystem extensions include implementation of IsFreeBSD(), IsLinux(), IsMacOS(), IsOSPlatform(), IsWindows() and alike.

Those functions should be compatible with platforms supported by Mono, for checking against Mono-specific platforms use IsOSPlatform(string platform), the exact names to check against can be found here.

#if NETFRAMEWORK
using OperatingSystem = JustArchiNET.Madness.OperatingSystemMadness.OperatingSystem;
#endif
using System;

namespace ThisIsMadness {
	public static class ThisIsSparta {
		public static void Scream() {
			if (OperatingSystem.IsWindows()) {
				// Windows logic
			} else {
				// Non-windows logic
			}
		}
	}
}

Other

Root JustArchiNET.Madness namespace also includes selected classes normally not available on .NET Framework, for example SupportedOSPlatform or non-generic TaskCompletionSource.

#if NETFRAMEWORK
using JustArchiNET.Madness;
#else
using System.Runtime.Versioning;
#endif

namespace ThisIsMadness {
	public static class ThisIsSparta {
		[SupportedOSPlatform("Windows")]
		public static void Scream() {
			// Obviously this doesn't have the effect you expect from your IDE, but at least you don't have to hide it behind #if
			// Besides, if you're targetting something else like net5.0 then it'll work as designed warning you about calls from other platforms.
		}
	}
}

FAQ

Do I need that #if NETFRAMEWORK clause?

If you're building only for .NET Framework exclusively, no, it's not required and actually quite useless code verbosity for you.

However, if you're targetting multiple frameworks out of which only one is .NET Framework (e.g. net5.0 and net48), then #if clause guarantees that madness won't embrace your other targets.

You don't want madness to embrace your other targets, do you?

It also becomes mandatory if you're building for multiple targets and you've followed our advice and conditionally included <PackageReference> only for .NET Framework. Other targets won't know about this namespace, so hiding the usage behind #if becomes obligatory. On the other hand, it's perfect, because it ensures you don't use our using where you don't intend to.

At the same time check out our hint above, as it's possible to add using clauses globally to the whole project, which won't require from you to pollute every file with a potential #if.

And what happens if I use Madness for other frameworks?

Nothing bad, if you ignore increased likelihood for compatibility issues, degraded performance, potential source code conflicts with original classes and all other mess that you really don't want to get into. Don't go deeper than you have to. We've been there before you, it's not pleasant. It's best to keep it sane for other targets, but we don't judge you, Madness supports netstandard2.0 and above, include it wherever you want to.

What if I need to combine Madness parts with .NET ones?

We've hidden our static classes deeper in our namespace for a reason - to decrease chance that you run into this issue. Usually it's enough for one #if on the top, as in our file extensions example above.

However, sometimes you can't help it, and you'll have to #if all the way through for those cases, still better than writing it yourself, right?

#if NETFRAMEWORK
using JustArchiNET.Madness;
#else
using System.Diagnostics;
#endif
using System;

namespace ThisIsMadness {
	public static class ThisIsSparta {
		internal static DateTime ProcessStartTime {
#if NETFRAMEWORK
			get => RuntimeMadness.ProcessStartTime.ToUniversalTime();
#else
			get {
				using Process process = Process.GetCurrentProcess();

				return process.StartTime.ToUniversalTime();
			}
#endif
		}
	}
}

If all else fails, you can in theory call Madness parts exclusively (since it's based on .NET Standard, not Framework per-se), so the above is rather a "perfect" example for not affecting your other targets negatively. You have to decide yourself between affecting code readability or compatibility and performance. Choose your poison. We recommend to keep Madness contained in .NET Framework exclusively, like in all our examples.

All of this is cool, but I'm missing XYZ for my needs...

Send a PR, Madness by default includes parts that we require ourselves in ArchiSteamFarm project and as you can guess, we can't rewrite everything that was made by thousands of developers in newer versions of .NET just to satisfy .NET Framework on its last leg.

For best results you should include exact classes, methods, properties and everything else, so source code requirements to make use of it are close to minimum and hopefully only initial using clause will be required to embrace the Madness.

We're also open for so-called "proxy" features in static classes that we already provide, to decrease burden of putting #if clauses everywhere. We've included all of those we require ourselves, such as:

public static class File {
	public static bool Exists(string? path) => System.IO.File.Exists(path);
}

This allows consumers to alias File to our implementation without additional burden - feel free to send a PR for those as well. If it helps you in any way to increase code quality and sanity for your original projects, Madness doesn't mind to take a hit for justified reason ☠️.


Attribution

Skull icon made by Freepik from Flaticon.

Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48 net481
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on JustArchiNET.Madness:

Package Downloads
ArchiSteamFarm.Library

ASF is a C# application with primary purpose of idling Steam cards from multiple accounts simultaneously.

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on JustArchiNET.Madness:

Repository Stars
BeyondDimension/SteamTools
🛠「Watt Toolkit」是一个开源跨平台的多功能 Steam 工具箱。
JustArchiNET/ArchiSteamFarm
C# application with primary purpose of farming Steam cards from multiple accounts simultaneously.
Version Downloads Last updated
3.10.0 766 1/12/2023
3.9.0 1,888 12/15/2022
3.8.0 2,482 10/27/2022
3.7.0 10,658 7/2/2022
3.6.0 2,659 6/19/2022
3.5.2 5,058 4/22/2022
3.5.1 1,046 4/13/2022
3.5.0 244 4/13/2022
3.4.0 707 4/2/2022
3.3.0 3,918 2/18/2022
3.2.1 4,885 1/23/2022
3.2.0 246 1/22/2022
3.1.1 3,687 12/12/2021
3.1.0 168 12/12/2021
3.0.0 2,905 12/4/2021
2.4.1 1,132 11/29/2021
2.4.0 1,092 11/29/2021
2.3.2 994 11/19/2021
2.3.1 611 11/19/2021
2.3.0 626 11/19/2021
2.2.1 265 11/18/2021
2.2.0 193 11/18/2021
2.1.0 261 11/17/2021
2.0.0 339 11/13/2021
2.0.0-alpha5 170 11/11/2021
2.0.0-alpha4 178 11/11/2021
2.0.0-alpha3 158 11/11/2021
2.0.0-alpha2 328 11/8/2021
2.0.0-alpha1 154 11/8/2021
1.5.0 753 11/8/2021
1.4.0 1,061 10/22/2021
1.3.1 1,787 9/5/2021
1.3.0 6,075 8/23/2021
1.2.0 406 8/19/2021
1.1.0 677 8/9/2021
1.0.0 325 8/7/2021
0.3.0 335 8/7/2021
0.2.0 276 8/5/2021
0.1.0 319 8/5/2021