JustArchiNET.Madness
3.6.0
Due to the fact that we've dropped support for .NET Framework in our other projects, we don't intend to develop Madness further. You're free to fork or re-use Madness components if you find them useful!
See the version list below for details.
dotnet add package JustArchiNET.Madness --version 3.6.0
NuGet\Install-Package JustArchiNET.Madness -Version 3.6.0
<PackageReference Include="JustArchiNET.Madness" Version="3.6.0" />
paket add JustArchiNET.Madness --version 3.6.0
#r "nuget: JustArchiNET.Madness, 3.6.0"
// Install JustArchiNET.Madness as a Cake Addin #addin nuget:?package=JustArchiNET.Madness&version=3.6.0 // Install JustArchiNET.Madness as a Cake Tool #tool nuget:?package=JustArchiNET.Madness&version=3.6.0
☠️ Madness
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.OperatingSystemMadness.OperatingSystem" Alias="OperatingSystem" />
<Using Include="JustArchiNET.Madness.PathMadness.Path" Alias="Path" />
<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
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- IndexRange (>= 1.0.0)
- Microsoft.AspNetCore.Hosting.Abstractions (>= 1.0.0)
- Microsoft.Bcl.AsyncInterfaces (>= 1.0.0)
- System.Memory (>= 4.5.0)
-
.NETStandard 2.1
- Microsoft.AspNetCore.Hosting.Abstractions (>= 1.0.0)
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
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
3.17.0 | 1,543 | 10/21/2023 | |
3.16.0 | 2,613 | 9/13/2023 | |
3.15.0 | 4,756 | 5/24/2023 | |
3.14.0 | 347 | 5/17/2023 | |
3.13.0 | 285 | 5/16/2023 | |
3.12.0 | 866 | 4/20/2023 | |
3.11.0 | 3,163 | 2/9/2023 | |
3.10.0 | 1,231 | 1/12/2023 | |
3.9.0 | 3,394 | 12/15/2022 | |
3.8.0 | 4,162 | 10/27/2022 | |
3.7.0 | 11,650 | 7/2/2022 | |
3.6.0 | 2,901 | 6/19/2022 | |
3.5.2 | 5,373 | 4/22/2022 | |
3.5.1 | 1,260 | 4/13/2022 | |
3.5.0 | 457 | 4/13/2022 | |
3.4.0 | 904 | 4/2/2022 | |
3.3.0 | 4,189 | 2/18/2022 | |
3.2.1 | 5,146 | 1/23/2022 | |
3.2.0 | 477 | 1/22/2022 | |
3.1.1 | 3,850 | 12/12/2021 | |
3.1.0 | 313 | 12/12/2021 | |
3.0.0 | 3,069 | 12/4/2021 | |
2.4.1 | 1,301 | 11/29/2021 | |
2.4.0 | 1,256 | 11/29/2021 | |
2.3.2 | 1,159 | 11/19/2021 | |
2.3.1 | 747 | 11/19/2021 | |
2.3.0 | 774 | 11/19/2021 | |
2.2.1 | 427 | 11/18/2021 | |
2.2.0 | 349 | 11/18/2021 | |
2.1.0 | 419 | 11/17/2021 | |
2.0.0 | 478 | 11/13/2021 | |
2.0.0-alpha5 | 266 | 11/11/2021 | |
2.0.0-alpha4 | 282 | 11/11/2021 | |
2.0.0-alpha3 | 275 | 11/11/2021 | |
2.0.0-alpha2 | 428 | 11/8/2021 | |
2.0.0-alpha1 | 266 | 11/8/2021 | |
1.5.0 | 910 | 11/8/2021 | |
1.4.0 | 1,231 | 10/22/2021 | |
1.3.1 | 1,939 | 9/5/2021 | |
1.3.0 | 6,328 | 8/23/2021 | |
1.2.0 | 526 | 8/19/2021 | |
1.1.0 | 819 | 8/9/2021 | |
1.0.0 | 480 | 8/7/2021 | |
0.3.0 | 503 | 8/7/2021 | |
0.2.0 | 426 | 8/5/2021 | |
0.1.0 | 512 | 8/5/2021 |