TheOmenDen.Shared
2023.3.17.2238
Prefix Reserved
See the version list below for details.
dotnet add package TheOmenDen.Shared --version 2023.3.17.2238
NuGet\Install-Package TheOmenDen.Shared -Version 2023.3.17.2238
<PackageReference Include="TheOmenDen.Shared" Version="2023.3.17.2238" />
paket add TheOmenDen.Shared --version 2023.3.17.2238
#r "nuget: TheOmenDen.Shared, 2023.3.17.2238"
// Install TheOmenDen.Shared as a Cake Addin #addin nuget:?package=TheOmenDen.Shared&version=2023.3.17.2238 // Install TheOmenDen.Shared as a Cake Tool #tool nuget:?package=TheOmenDen.Shared&version=2023.3.17.2238
The Omen Den Shared Library
This is just a grouping of common classes that are used within every application that The Omen Den aims to provide as a company, and is free to modify, redistribute, and use elsewhere
- Especially since this library is sure to not be unique to us.
- Attributions for credits on each release are defined below
Goals that we aim for:
- Relevant extensions across The Omen Den's software applications
- Exception calling, and custom exceptions
- Pooling extensions for StringBuilder and Arrays
- Hopefully working towards far less overhead than constantly newing these types up
- In the case of arrays, adding "slicing" SubArray functionality
- Custom Enumerations
- Providing ways to grade exceptions via gravity
- Providing ways to use "smarter" enumerations for differing control flow
- Provides two structs
Conditions and Consequences
that can be chained together against theEnumerationBase
implementations - Inspired by:
- Provides simple LINQ methods for
ReadOnlySpan<T>
- Base Record types for
QueryStrings
- AsyncLazyInitializer type sourced from: Microsoft Dev Blogs
- Extensions on the
Type Type
to allow for easier retrieval of ancestors - Provides
Progress Bars
that can also be thread-safe, as well as a simple progress indicator.- Gives the caller the ability to specify a change in the
ConsoleColor
with any one of the provided colors. - Provides a relatively smooth, and rate-adjustable animation on the progress indicator
- Gives the caller the ability to specify a change in the
- Provides
Guard
methods that can be used to help control the flow and validation of models and creation of various components in an application domain.
Async Stream Handling Features
- Provided in the
AsynchronousStreamOutcome
set of extensions are a few methods for capturingOperationOutcome
during the iterations of anIAsyncEnumerable<T>
- The
T
in question must implement ourIEntity
interface. - We aim to work solely with asynchronous iterations provided by an
await foreach()
pattern - We also aim to provide a simple, and easy to interpret API for further processing and alignment by avoiding an underlying
try...catch
within the Async Iterator.
- The
- Our current implementation allows for the simplicity of just providing a long running delegate of an individual operation.
Func<in T, in CancellationToken, out ValueTask<OperationOutcome>>
- This guarantees that the underlying operation is asynchronous
- This also ensures that the operation returns an
OperationOutcome
object
- With this provided, our intent on design is twofold -
- Firstly We remove the basis for throwing an exception over the stream.
- Secondly We allow for individual failures to occur during the stream.
- With this approach, we aim to allow for multiple failures to occur during the stream, while maintaining a consistent reporting behavior to allow for a more streamlined client experience.
- We also aim for the
Tuple<T,OperationOutcome>
coupling to be a launching strategy for further processing.
EnumerationBase
- These
Record Types
are implemented as such:EnumerationBase<TKey>
- Similar to the standard Enumeration
Enum
type that you will see inC#
but provides the ability to work with Conditions (When) and Consequences (Then) allowing for the expansion of logic on top of Enumerations. - We provide a way to customize this further by using
EnumrationBase<TKey, TEnumeration>
to define a customized "backing field" for your own design. - We also provide guards, and relevant exceptions to assist in runtime "Early Swift Failure" practices.
- Similar to the standard Enumeration
EnumerationFlagBase<TKey>
- This record allows for your enumerations to be extended to have a similar functionality as working with bit flags on your standard
C#
enumerations. - This is further enhanced by the use of our
Condtions (When) ... Consequences (Then)
pattern - allowing for more robust and well defined logic. - Strictly enforced by making the definition of the enum require an integer backing field using powers of two (2<sup>n</sup>)
- 2,4,8,16... 2<sup>n</sup>
- This record allows for your enumerations to be extended to have a similar functionality as working with bit flags on your standard
Guards
- We have created a
Guard
partial class system- Our aim/intention with this is to allow for a "fail early" strategy at your domain's edge.
- We encourage you NOT to use these classes within your business logic/application domain since that seems to be an anti-pattern.
- There are also differing typed exceptions that are thrown per condition, as well as provided exception message templates.
- If you desire to define your own custom Guard - You would want to work with the
Guard.FromCondition
method. This allows for the passing of a delegate that has a boolean result, and anException
object as an outcome.- e.g.
Guard.FromCondition(Func<Boolean>, Exception exception)
- e.g.
Random Generations
- The need for generating random values across threads has been shown for us at The Omen Den - especially as we work on Crows Against Humility
- Our aim/intention was to provide a thread safe implementation of .NET's
Random
. - We of course will credit Alexey from [this stack overflow] post for the basis of our design and documentation - it is important to continue to recognize where our knowledge comes from.
ThreadSafeRandom
implements bothIDisposable
andIAsyncDisposable
to allow for the destruction/freeing of resources used byThreadLocal
- We don't use a locking mechanism here, to avoid the complications and relative expense
- However, we also recognized that by using a static implementation, there could be complications from "newing" up an instance
- Our aim/intention was to provide a thread safe implementation of .NET's
- We have also incorporated this approach in our
LINQ
implementations of random element retrieval.This article by Paul Scharf provided enough basis and inspiration for our approach
With the ability to provide some basic optimizations for the following implementations:
ICollection<T>
T[]
andList<T>
- we were able to see linear performance, as well as reduced allocationsWe also have the methods for Arrays (
T[]
) and ListsList<T>
as separate methods with the types appended to their suffix. (e.g.GetRandomElementFromArray
)We split up our methods into two main ideas
GetRandomElement(s)
- To retrieve the actualTValue
from the supplied source collectionGetRandomIndex(Indexes)
- To retrieve anIndex
struct for further usage from the supplied source collection.
We do also have benchmarks available, but we also believe that O(n) (mentioned in the above article) - was probably the most optimized we could get. The most optimizations we retrieved were from space saving methods
A few Benchmarks, as generated by Benchmark.NET (small array - 100 ints, medium array 100,000 ints, large array 1,000,000 ints)
Method | Mean | Error | StdDev | Gen0 | Allocated |
---|---|---|---|---|---|
GetRandomElementFromSmallArray | 52.35 ns | 0.374 ns | 0.415 ns | - | - |
GetRandomElementFromMediumArray | 43.78 ns | 0.625 ns | 0.585 ns | - | - |
GetRandomElementFromLargeArray | 46.94 ns | 0.658 ns | 0.856 ns | - | - |
GetRandomElementFromSmallList | 41.56 ns | 0.595 ns | 0.557 ns | - | - |
GetRandomElementFromMediumList | 31.98 ns | 0.631 ns | 0.559 ns | - | - |
GetRandomElementFromLargeList | 39.39 ns | 0.818 ns | 1.433 ns | - | - |
GetSmallAmountOfRandomElementsBenchmarkArray | 155.03 ns | 1.863 ns | 1.651 ns | 0.0076 | 48 B |
GetMediumAmountOfRandomElementsBenchmarkArray | 22,297.34 ns | 246.435 ns | 192.401 ns | - | 48 B |
GetLargeAmountOfRandomElementsBenchmarkArray | 2,314,022.18 ns | 23,111.151 ns | 20,487.433 ns | - | 50 B |
GetSmallAmountOfRandomElementsBenchmarkList | 169.68 ns | 1.296 ns | 1.212 ns | 0.0076 | 48 B |
GetMediumAmountOfRandomElementsBenchmarkList | 23,649.32 ns | 407.402 ns | 361.151 ns | - | 48 B |
GetLargeAmountOfRandomElementsBenchmarkList | 2,776,298.51 ns | 53,700.678 ns | 52,741.246 ns | - | 50 B |
GetSmallAmountOfRandomElementsBenchmark | 239.36 ns | 3.045 ns | 2.700 ns | 0.0153 | 96 B |
GetMediumAmountOfRandomElementsBenchmark | 24,046.92 ns | 197.307 ns | 174.908 ns | - | 96 B |
GetLargeAmountOfRandomElementsBenchmark | 2,854,750.20 ns | 27,621.984 ns | 24,486.170 ns | - | 98 B |
Model Contracts
IUser
- A simple interface to mark the definition of a
user
.Id
- a GUID/UUID that allows for easy storage and retrieval of user information.Email
- an individual's email address.Name
- the name of the user.IsAuthenticated
- indicates whether the user is authenticated.Key
- the key associated with the user (integer based).
- A simple interface to mark the definition of a
ITenant
- A representation of the container for organization/business items, logic, and information.
Id
- a GUID/UUID that allows for easy storage and retrieval of tenant information.Code
- The code associated with the tenant.Name
- the name of the tenant.Key
- the key associated with the tenant (integer based).
- A representation of the container for organization/business items, logic, and information.
IEntityKey
- Provides a generic interpretation to help distinguish entities from each other.
Id
- a GUID/UUID that allows for easy storage and retrieval.CreatedAt
- a timestamp marking the entity's creation.ITenant
- The Tenant that entity is associated with.IUser
- the originator/creator of the entity.
- Provides a generic interpretation to help distinguish entities from each other.
IEntity
- A simple marker interface that provides an implementation with a way to define a unique
IEntityKey
on an Entity.IEntityKey
the unique key associated with the entity.
- A simple marker interface that provides an implementation with a way to define a unique
Specifications
- We've implemented a basic specification pattern. The idea here is that it should be robust enough to use in a common case, but not too complicated that it will require a steep learning curve
- We've added the following logical operations to the specification pattern
AND
which combines two specifications and returns the combined result using the AND logical truth tableOR
which combines two specifications and returns the combined result using the OR logical truth tableNOR
which combines two specifications and returns the combined result using the NOR logical truth table (Bubble And)NAND
which combines two specifications and returns the combined result using the NAND logical truth table (Bubble Or)NOT
which inverts the logical truth table for the provided specification.
- These do use System.Linq.Expressions, and are implemented over record types, with the idea that a specification should be weighed in it's usage by the intent of the domain it belongs to. This also allows us to have a sort of better knowledge of thread safety and mitigate certain performance issues. We're hoping to continue to improve upon these metrics, and can provide unit test coverages, as well as further performance metrics.
- An example of using this pattern can be found in the Unit Tests Repository, which is located at TheOmenDen.Shared.Tests.
TODOs:
- Provide better source generation for our generic implementations
- Provide clearer, and more accessible documentation
- General clean-up, and optimizations
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 is compatible. 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
- System.Linq.Async (>= 6.0.1)
-
net7.0
- System.Linq.Async (>= 6.0.1)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on TheOmenDen.Shared:
Package | Downloads |
---|---|
TheOmenDen.Shared.Logging
A collection of logging utilities that are used throughout The Omen Den's applications. Also provides an eventtype enricher for Serilog |
|
TheOmenDen.Shared.Interfaces
This package contains the interfaces that can used for various implementations, and some of the models behind them for Tenancy and User based applications. |
|
TheOmenDen.Shared.Services
A collection of the service implementations used throughout the various apps that The Omen Den develops. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2023.11.27.49 | 1,204 | 11/27/2023 |
2023.3.25.112 | 3,170 | 3/25/2023 |
2023.3.17.2238 | 389 | 3/18/2023 |
2023.1.15.141 | 606 | 1/15/2023 |
2022.11.13.2149 | 1,218 | 11/14/2022 |
2022.10.8.41 | 2,435 | 10/8/2022 |
2022.9.19.1408 | 993 | 9/19/2022 |
2022.8.27.345 | 697 | 8/27/2022 |
2022.8.13.1752 | 543 | 8/13/2022 |
2022.7.26.331 | 828 | 7/26/2022 |
2022.7.19.110 | 626 | 7/19/2022 |
2022.7.13.1515 | 546 | 7/13/2022 |
2022.7.11.1017 | 517 | 7/11/2022 |
Add guard classes, add enumeration record types