wan24-Core
1.4.0
See the version list below for details.
dotnet add package wan24-Core --version 1.4.0
NuGet\Install-Package wan24-Core -Version 1.4.0
<PackageReference Include="wan24-Core" Version="1.4.0" />
paket add wan24-Core --version 1.4.0
#r "nuget: wan24-Core, 1.4.0"
// Install wan24-Core as a Cake Addin #addin nuget:?package=wan24-Core&version=1.4.0 // Install wan24-Core as a Cake Tool #tool nuget:?package=wan24-Core&version=1.4.0
wan24-Core
This core library contains some .NET extensions:
- Bootstrapping
- Disposable base class for disposable types, which supports asynchronous
disposing
- Dispose attribute for fields/properties which should be disposed automatic when disposing
- Type helpr (type loading)
- Secure byte array, which clears its contents when disposing
- Pool rented array as disposable object
- Byte array extensions
- Endian conversion
- Bit-converter (endian-safe)
- UTF-8 string decoding
- Clearing
- Array helper extensions
- Offset/length validation
- Enumerable extensions
- Combine enumerables
- Chunk enumerables
- Reflection extensions
- Automatic parameter extension when invoking a method (with DI support)
- Synchronous/asynchronous method invokation
- Automatic constructor invokation using a given parameter set (with DI support)
- Nullability detection
- Delegate extensions
- Delegate list invokation (with or without return values, with DI support)
- Asynchronous delegate list invokation (with or without return values, with DI support)
- Task extensions
- Result getting of a generic task
- Asynchronous task list awaiting
- Shortcuts for await configurations
- DI helper
- Service provider adoption
- DI object factory delegates
- Asynchronous DI object factory delegates
- Enumeration extensions
- Get enumeration value display string from
DisplayTextAttribute
or usingToString
(fallback) - Remove flags of a mixed enumeration value
- Get only flags of a mixed enumeration value
- Value validation
- Get enumeration value display string from
- Number extensions
- Determine if a type is a number
- Determine if a number type is unsigned
- Bit-converter (endian-safe)
- Determine if a number (or any
IComparable
) is within a range
- Collection extensions
- Add a range if items
- JSON helper
- Exchangeable JSON encoder/decoder delegates (using
System.Text.Json
per default)
- Exchangeable JSON encoder/decoder delegates (using
- JSON extensions
- Encode an object
- Decode from a type
- Decode a string
- Object extensions
- Type conversion
- Determine if a value is within a list of values
- String extensions
- Get UTF-8 bytes
- Queue worker (for actions and/or items)
- Parallel queue worker (for actions and/or items)
ParallelAsync
implementation- Base class for a hosted worker, which implements the
IHostedService
interface (timed or permanent running) EventThrottle
for throttling event handler callsProcessThrottle
for throttling a processing channelOrderedDictionary<tKey, tValue>
is used for working with indexed key/value pairsTimeout
will count down and raise an event, if not reset before reaching the timeout
How to get it
This library is available as (NuGet package "wan24-Core")[https://www.nuget.org/packages/wan24-Core/].
Bootstrapping
The Bootstrapper.Async
method calls all static methods having the
BootstrapperAttribute
. In order to be able to find the methods, it's
required to add the BootstrapperAttribute
to the assembly.
You may also ad the BootstrapperAttribute
to a type and/or the bootstrapper
method, in case the assembly contains multiple of them.
The bootstrapper methods may consume parameters which are available from the DI helper. The method may be synchronous or asynchronous. The method can't be defined in a generic class, and it can't be generic itself.
[assembly:Bootstrapper(typeof(YourBootstrapper),nameof(YourBootstrapper.BootstrapperMethod))]
public static class YourBootstrapper
{
public static async Task BootstrapperMethod()
{
// Perform your bootstrapping here
}
}
// Call the bootstrapper somewhere in your apps initialization code
await Bootstrap.Async();
The BootstrapperAttribute
can be initialized with a numeric priority. The
bootstrapper will order the found bootstrapping methods by priority, where the
one with the highest number will be executed first (assembly and type
priorities count, too). At last there's a assembly location, type and method
name sorting. Bootstrapper methods will be executed sequential.
If you give a type and a method name to the assembly BootstrapperAttribute
,
you won't need to add the attribute to the type and the method.
During bootstrapping, the cancellation token which was given to the
Bootstrap.Async
method, can be injected to a bootstrappers method parameters.
Type helper
If you use the TypeHelper.AddTypes
method, the unknown assemblies of the
added types will be added as searchable assemblies automatic.
You may attach to the TypeHelper.OnLoadType
event for handling requests
more dynamic.
The TypeHelper.GetType
method will try Type.GetType
first and fall back to
the helper, if no type was found.
DI helper
In order to make DI (dependency injection) working, you need to
- set a
DiHelper.ServiceProvider
and/or - add
DiHelper.(Async)ObjectFactories
The DiHelper.GetDiObjectAsync
method will try to resolve the request
synchronous, first. But the DiHelper.GetDiObject
won't try asynchronous
object factories.
Mixed enumeration value
A mixed enumeration contains X bits enumeration values, and Y bits flags:
public enum MixedEnum : int
{
None = 0,
Value1 = 1,
Value2 = 2,
Value3 = 3,
...
Flag1 = 1 << 8,
Flag2 = 1 << 9,
FLAGS = Flag1 | Flag2 // Required to identify flags
}
The FLAGS
value helps these extension methods to handle flag values:
MixedEnum value = MixedEnum.Value1 | MixedEnum.Flag1,
valueOnly = value.RemoveFlags(),// == MixedEnum.Value1
flagsOnly = value.OnlyFlags();// == MixedEnum.Flag1
Unsafe code
The library uses unsafe code. If you don't want/need that, you can compile the
library with the NO_UNSAFE
compiler constant to disable any unsafe
operation. Remember to unset the unsafe compiler option, too!
Disposable base class
The DisposableBase
implements the IDisposable
and IAsyncDisposable
interfaces. It provides some helpers and events, and also the
DisposeAttribute
, which can be applied to fields and properties which you
wish to dispose automatic when disposing.
When your type derives from the DisposableBase
, you'll need to implement the
abstract Dispose
method:
protected override Dispose(bool disposing)
{
// Your dispose logic here
}
There are measures to avoid that this method is being called twice.
To implement custom asynchronous disposing:
protected override async Task DisposeCore()
{
// Your dispose logic here
}
In order to make the DisposeAttribute
working, you have to call the
protected method DisposeAttributes
or DisposeAttributesAsync
.
The IsDisposing
property value will be true
as soon as the disposing
process started, and it will never become false
again. The IsDisposed
property value will be true
as soon as the disposing process did finish.
Queue worker
using QueueWorker worker = new();
await worker.EnqueueAsync((ct) =>
{
// Do any background action here
});
The QueueWorker
class can be extended as you need it.
The ParallelQueueWorker
requires a number of threads in the constructor,
which defines the degree of parallelism, in which enqueued tasks will be
processed.
Queue item worker
using QueueItemWorker<ItemType> worker = new();
await worker.EnqueueAsync(new ItemType());
The QueueItemWorker<T>
class can be extended as you need it.
The ParallelItemQueueWorker<T>
requires a number of threads in the
constructor, which defines the degree of parallelism, in which enqueued items
will be processed.
ParallelAsync
Using the .NET parallel implementation it's not possible to invoke
asynchronous item handlers. For this you can use the
ParallelAsync.ForEachAsync
method, which uses a parallel item queue worker
in the background for asynchronous processing.
Hosted worker
public class YourHostedWorker : HostedWorkerBase
{
public YourHostedWorker() : base() { }
protected override async Task WorkerAsync()
{
// Perform the service actions here
}
}
The hosted worker implements the IHostedService
interface and can be
extended as you need it.
Timed hosted worker
public class YourHostedWorker : TimedHostedWorkerBase
{
public YourHostedWorker() : base(interval: 500) { }
protected override async Task WorkerAsync()
{
// Perform the service actions here
}
}
This example uses a 500ms timer. Based on the defined timer type, the interval will be processed in different ways:
Default
: Next worker run is now plus the interval (used by default)Exact
: Next worker run is now plus the interval minus the processing duration (used, if the start time of the processing is important)ExactCatchingUp
: AsExact
, but catching up missing processing runs without delay, if a worker run duration exceeds the interval (used, if the number of worker runs is important)
Using the SetTimerAsync
method you can change the timer settings at any
time. If you give the nextRun
parameter, you may set a fixed next run time
(which won't effect the given interval, but just force the service to run at a
specific time for the next time).
NOTE: The nextRun
parameter will also force the service to (re)start!
By setting the property RunOnce
to true
, the service will stop after
running the worker once. In combination with the SetTimerAsync
parameter
nextRun
you can execute the worker at a specific time once.
The hosted worker implements the IHostedService
interface and can be
extended as you need it.
EventThrottle
public class YourType : DisposableBase
{
protected readonly YourEventThrottle EventThrottle;
public YourType() : base() => EventThrottle = new(this);
// This method will raise the OnEvent
public void AnyMethod()
{
RaiseOnEventThrottled();
}
protected override Dispose(bool disposing) => EventThrottle.Dispose();
// Delegate for OnEvent
public delegate void YourTypeEvent_Delegate();
// Event to throttle
public event YourTypeEvent_Delegate? OnEvent;
// Raise the OnEvent using the event throttle
protected void RaiseOnEventThrottled() => EventThrottle.Raise();
// Finally let the event handlers process the event
protected void RaiseOnEvent() => OnEvent?.Invoke();
// Event throttle implementation
public class YourEventThrottle : EventThrottle
{
// Throttle the event handling down to max. one handling per 300ms
public YourEventThrottle(YourType instance) : base(timeout: 300) => Instance = instance;
public YourType Instance { get; }
protected override HandleEvent(DateTime raised, int raisedCount)
{
Instance.RaiseOnEvent();
}
}
}
If AnyMethod
is being called, the event will be forwarded to the event
throttle, which decides to throttle or raise the event. If AnyMethod
was
called three times within 300ms, the first call will be executed in realtime,
while the 2nd and the 3rd call will be sqashed and executed once 300ms after
the 1st call was processed.
This example assumes you're working with a real event - but you may throttle any event (which may not be a real event) using throttling logic.
ProcessThrottle
public class YourProcessThrottle : ProcessThrottle
{
// Throttle to processing one object per second
public YourProcessThrottle() : base(limit: 1, timeout: 1000) { }
// Processing API using a timeout
public async Task<int> ProcessAsync(Memory<bool> items, TimeSpan timeout)
=> await ProcessAsync(items.Length, (count) =>
{
await Task.Yield();
Span<bool> toProcess = items.Span[..count];
items = items[count..];
// Process toProcess
}, timeout);
// Processing API using a cancellation token
public async Task<int> ProcessAsync(Memory<bool> items, CancellationToken token = default)
=> await ProcessAsync(items.Length, (count) =>
{
await Task.Yield();
Span<bool> toProcess = items.Span[..count];
items = items[count..];
// Process toProcess
}, token);
}
The example will throttle the processing to a maximum of one object per
second. Multiple threads may call ProcessAsync
concurrent - processing will
be organized thread-safe.
The return value of ProcessAsync
is the number of objects processed until
timeout or cancelled.
The processing delegate shouldn't care about the timeout or if cancelled and just process the given number of objects.
NOTE: A usage gap will slide the throttling timer. Example:
The timeout was set to 3 objects per 100ms. Now processing goes like this:
- First processed object on
0ms
will activate the throttling timeout - Next processed object on
10ms
will increase the object throttling counter - Next processed object on
110ms
will reset the throttling timeout and counter (the usage gap of 100ms does exceed the timeout) - Next 2 processed objects on
120ms
will activate the throttle - Next object will have to wait until the throttle was released
- The throttle will be released on
210ms
, which allows the last object to be processed now
In short words: The throttle timer will not reset in an fixed interval, but the interval starts when processing items.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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. |
-
net6.0
- Microsoft.Extensions.Hosting.Abstractions (>= 7.0.0)
NuGet packages (14)
Showing the top 5 NuGet packages that depend on wan24-Core:
Package | Downloads |
---|---|
Stream-Serializer-Extensions
Serializer extensions for .NET Stream objects. |
|
wan24-Compression
Compression helper |
|
wan24-Crypto
Crypto helper |
|
wan24-Crypto-BC
Bouncy Castle adoption to wan24-Crypto |
|
wan24-Compression-LZ4
LZ4 adoption for wan24-Compression |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.45.0 | 87 | 11/16/2024 |
2.44.0 | 105 | 11/10/2024 |
2.43.0 | 96 | 11/3/2024 |
2.42.0 | 427 | 10/27/2024 |
2.41.0 | 82 | 10/21/2024 |
2.40.0 | 90 | 10/20/2024 |
2.39.0 | 100 | 9/29/2024 |
2.38.0 | 647 | 9/21/2024 |
2.37.0 | 117 | 9/15/2024 |
2.36.0 | 296 | 9/8/2024 |
2.35.0 | 230 | 8/24/2024 |
2.34.0 | 662 | 8/16/2024 |
2.33.0 | 233 | 8/4/2024 |
2.32.0 | 423 | 7/13/2024 |
2.31.0 | 394 | 7/6/2024 |
2.30.0 | 185 | 6/29/2024 |
2.29.0 | 352 | 6/22/2024 |
2.28.0 | 327 | 6/15/2024 |
2.27.0 | 100 | 6/8/2024 |
2.26.0 | 123 | 6/1/2024 |
2.25.0 | 130 | 5/26/2024 |
2.24.0 | 136 | 5/20/2024 |
2.23.0 | 175 | 5/11/2024 |
2.22.0 | 338 | 5/9/2024 |
2.21.0 | 142 | 5/5/2024 |
2.20.0 | 164 | 4/28/2024 |
2.19.0 | 160 | 4/20/2024 |
2.18.1 | 161 | 4/14/2024 |
2.18.0 | 347 | 4/12/2024 |
2.17.0 | 126 | 4/7/2024 |
2.16.0 | 218 | 3/30/2024 |
2.15.1 | 124 | 3/30/2024 |
2.15.0 | 115 | 3/30/2024 |
2.14.0 | 141 | 3/24/2024 |
2.13.0 | 151 | 3/17/2024 |
2.12.0 | 192 | 3/15/2024 |
2.11.0 | 156 | 3/10/2024 |
2.10.1 | 130 | 3/10/2024 |
2.10.0 | 232 | 3/9/2024 |
2.9.2 | 309 | 3/2/2024 |
2.9.1 | 135 | 3/2/2024 |
2.9.0 | 168 | 3/2/2024 |
2.8.0 | 141 | 2/25/2024 |
2.7.1 | 130 | 2/25/2024 |
2.7.0 | 116 | 2/25/2024 |
2.6.0 | 277 | 2/24/2024 |
2.5.0 | 120 | 2/20/2024 |
2.4.0 | 127 | 2/18/2024 |
2.3.2 | 190 | 2/17/2024 |
2.3.1 | 127 | 2/17/2024 |
2.3.0 | 124 | 2/17/2024 |
2.2.0 | 402 | 1/20/2024 |
2.1.0 | 128 | 12/23/2023 |
2.0.0 | 203 | 12/17/2023 |
1.43.0 | 164 | 11/27/2023 |
1.42.0 | 298 | 11/11/2023 |
1.41.2 | 124 | 11/4/2023 |
1.41.1 | 121 | 11/4/2023 |
1.41.0 | 121 | 11/4/2023 |
1.40.0 | 267 | 10/29/2023 |
1.39.0 | 279 | 10/21/2023 |
1.38.2 | 150 | 10/15/2023 |
1.38.1 | 322 | 10/14/2023 |
1.38.0 | 139 | 10/14/2023 |
1.37.0 | 141 | 10/13/2023 |
1.36.0 | 327 | 10/7/2023 |
1.35.0 | 215 | 10/1/2023 |
1.34.0 | 204 | 9/27/2023 |
1.33.0 | 127 | 9/20/2023 |
1.32.1 | 312 | 9/19/2023 |
1.32.0 | 117 | 9/19/2023 |
1.31.1 | 173 | 9/16/2023 |
1.31.0 | 188 | 9/16/2023 |
1.30.1 | 274 | 9/10/2023 |
1.30.0 | 139 | 9/10/2023 |
1.29.0 | 323 | 9/3/2023 |
1.28.0 | 144 | 8/26/2023 |
1.27.0 | 146 | 8/19/2023 |
1.26.0 | 166 | 8/5/2023 |
1.25.1 | 276 | 7/30/2023 |
1.25.0 | 266 | 7/30/2023 |
1.24.0 | 390 | 7/22/2023 |
1.23.0 | 139 | 7/9/2023 |
1.22.0 | 144 | 6/25/2023 |
1.21.0 | 165 | 6/24/2023 |
1.20.0 | 162 | 6/17/2023 |
1.19.0 | 207 | 6/11/2023 |
1.18.2 | 160 | 6/10/2023 |
1.18.1 | 160 | 6/9/2023 |
1.18.0 | 349 | 6/8/2023 |
1.17.0 | 147 | 6/4/2023 |
1.16.0 | 491 | 6/3/2023 |
1.15.0 | 320 | 5/29/2023 |
1.14.0 | 153 | 5/29/2023 |
1.13.0 | 155 | 5/28/2023 |
1.12.0 | 326 | 5/27/2023 |
1.11.0 | 146 | 5/24/2023 |
1.10.0 | 147 | 5/23/2023 |
1.9.0 | 136 | 5/22/2023 |
1.8.2 | 319 | 5/20/2023 |
1.8.1 | 159 | 5/20/2023 |
1.8.0 | 153 | 5/20/2023 |
1.7.1 | 174 | 5/13/2023 |
1.7.0 | 209 | 5/11/2023 |
1.6.1 | 1,522 | 4/26/2023 |
1.6.0 | 393 | 4/25/2023 |
1.5.0 | 423 | 4/22/2023 |
1.4.0 | 168 | 4/22/2023 |
1.3.0 | 306 | 4/16/2023 |
1.2.0 | 251 | 4/10/2023 |
1.1.0 | 191 | 4/7/2023 |
1.0.1 | 206 | 4/1/2023 |