Skip to content

jjvanzon/JJ.Framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4,111 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔩 JJ.Framework

📔 Contents

📢 Introduction

JJ.Framework are extensions of the .NET Framework: the nuts, bolts and screws of software development: reusable components. Some of which might be expected to be there in .NET, but seem to be missing there.

JJ.Framework contains reusable code, that was produced along with real-life applications.

🏋️ Stability

No software is bug free, but extra effort was made, testing the JJ.Framework components, that were published to NuGet which includes automated testing.

The ones not on NuGet are available as a sneek peek in JJs-Pre-Release-Package-Feed. But those may be used with caution, because they may not be tested that well. Those may need some more unit testing and could still be a bug or two in it.

🏡 In-House

JJ.Framework was made in the spirit of: small things: develop your own, instead of importing a huge framework.

JJ.Framework components are compact: a couple of kilobytes each.

Developed in-house so that it could be adapted and extended as needed. It did not have to be complete, because then we would just extend it.

If a bug was found in the development of an app, we could just correct the JJ.Framework as needed and release a stable app.

Of course, this 'in-house development' argument does not apply, when other people use it. But I think these extensions could be of use to others too.

🏛️ History

Any reusable code independent of a particular business domain, was moved to this JJ.Framework, for reuse. The reusable code was gathered up between 2010 and 2026. It was a hobby project. But something similar to this framework, was also developed professionally in a team of 7 of which I was the technical lead at the time.

🍱 Modularization

JJ.Framework tends to have a separate assembly for each part of the .NET Framework that it extends. Separation may be found between technical aspects. That may allow being specific, on which parts of .NET an application becomes dependent.

JJ.Framework also likes to decouple platform-specific implementation details and hide them behind generalized interfaces.

💁 Platform Compatibility

That grip on dependency, was once a good plan for platform compatibility. Some of JJ.Framework is still based on .NET 4.6.1 trying to keep it compatible with Mono. Around 2015 JJ.Framework was tested to be reasonably compatible with Mono and by extension Android, iOS and Windows Phone. This was before newer technology like .NET Standard and .NET 5 + emerged, which could make platform-compatibility a bit more doable. For this reason, some of the JJ.Framework is currently being ported to a newer .NET, but this is still in progress.

📋 Release Notes

2025-03-31 | 1.9 : Build.csproj

  • Internal tooling
  • Triggers initialization at start of JJ.Framework solution build.

2025-06-14 | 2.5 : Existence.Core

2025-06-24 | 2.6 : Flags

  • JJ.Framework.Existence.Core
  • spaceMatters flags everywhere
  • caseMatters replaced ignoreCase
  • StringBulder/string more combos possible
  • x.In(a, b, c) extension favored over static In(x, a, b, c)

2025-07-02 | 2.7/0.250 : Legacy Lineage

2025-07-21 | 2.8/0.250 : Trimmable Libs

2026-01-25 | 2.9 : zeroMatters

2026-01-27 | 3.0/0.250 : .NET 10

  • Upgraded with explicit support for .NET 10

2026-01-28 | 3.1 : Less Prios

  • JJ.Framework.Existence.Core
  • Simplify overload picking removing some [Prio] attributes
  • Sacrifices direct use of keywords e.g. Coalesce(null, "Hallo"); not a real use case anyway.

2026-01-30 | 3.2/0.250 : Leading Flags - Coalesce

2026-01-31 | 3.3 : Leading Flags - Contains

2026-02-01 | 3.4 : Leading Flags - FilledIn

2026-02-17 | 3.7 : Clash of the Booleans

  • JJ.Framework.Existence.Core
  • Leading flags for Has/Is/In/IsNully (supplements trailing flags)
  • Improved Coalesce resolution and performance for 4+ values and collections.
  • Added overloads for reduced clashes between bool flags and value lists.
  • Various non-critical renames for clarity and modularity.
  • JJ.Framework.Common.Core
  • OverloadByName helper for an optional parameter trick to simulate overloading by name, not normally possible in C#.

2026-02-23 | 3.8/0.250 Business.Legacy

  • JJ.Framework.Business.Legacy
  • Release of historic version. Fullly covered with meaningful tests. Features:
  • EntityStatusManager and GetListIsDirty:
  • Framework-agnostic New/Deleted/Dirty flag container.
  • ISideEffect for keeping business logic units separated.
  • Bug fix: Entity status New and Deleted were accidentally stored as Dirty.

2026-02-26 | 3.9/0.250 : IO.Legacy

  • JJ.Framework.IO.Legacy
  • Full meaningful test coverage, and member docs.
  • Release of historic version 0.250.
  • Features:
  • CsvReader: simple streaming CSV reader supporting quoted fields and escaped double-quotes ("").
  • StreamHelper: convenience conversions between Stream, byte[] and string
  • ReadStruct/WriteStruct: methods for simple reading and writing structs to streams.
  • Bug fix: CsvReader preserves a trailing escaped quotes
  • Bug fix: CsvReader solved crash over trailing new line

2026-03-13 | 4.0/0.250 : Reflection.Legacy Re-Release

  • 2018 variant of ReflectionCacheLegacy moved from
  • Reflection.Core to
  • Reflection.Legacy with meaningful test coverage.
  • Trimming/AOT compatiblity.
  • Auto-run trim test
  • upon build
  • and inside NCrunch.

2026-03-15 | 4.1/0.251 : Validation.Legacy

  • JJ.Framework.Validation.Legacy
  • Historic version + full meaningful test coverage / IntelliSense docs / code trimming / native AOT support
  • .NET 10, 9, 8, 7, 6, 5, 4.6.1 / .NET Standard 2.0, 2.1
  • FluentValidator syntax:
    For(() => player.TotalScore, "Total Score").Min(0).Max(100);
  • NotNull, NotNullOrWhiteSpace, In, Is, IsNot, NotZero, Above, Min, Max, NotInteger, IsEnumValue
  • IValidator / ValidatorBase members:
    IsValid (boo), ValidationMessages, Verify() (throws)
  • Sub-validators and message prefixes:
    "Address: Street is required."
  • Localization: English (en-US) and Dutch (nl-NL)

2026-04-04 | 4.4/0.252 : PlatformCompatibility.Core Initial , Validation.Legacy Docs

2026-04-08 | 4.5/0.253 : Math Legacy

2026-04-25 | 4.6/0.254 : StringResources Legacy

+ Integrity Checker + Assert.Throws Syntax

  • JJ.Framework.StringResources.Legacy
  • 2015: Limited set of reusable string resources
  • 2020: Reusable tester verifying integrity
  • 2026: Extensions:
  • Placeholder verification
  • Resource and formatter classes
  • Static and instance members
  • Free to chose fallback culture
  • Optional trace logging
  • Customization options
  • Wide .NET version compatibility, Trimming/AOT support
  • IntelliSense docs, 100% meaningful test coverage
  • JJ.Framework.Testing.Core
  • Throws methods syntax shorter

2026-06-24 | 4.7/0.255 : Compilation.Core Preview

+ Various Fixes

  • JJ.Framework.Compilation.Core
  • Brand new dotnet.exe CLI wrapper. Run compilations and other dotnet actions programmatically at runtime.
  • Preview release. Works in general. More coverage desired. More features desired.
  • JJ.Framework.Configuration.Core
  • Auto-copy config files from proj to bin as classic System.Configuration did for you.
  • JJ.Framework.Configuration.Legacy
  • Prevent leaking System.Configuration.ConfigurationManager reference transiently to avoid clashes with older .NET versions.
  • JJ.Framework.Testing.Core
  • Show tested argument expression more often, even when a custom message provided, which would formerly override it.
  • Complete test suite against regression.
  • TestRunner parallel by default but respect [DoNotParallelize] attribute. Race conditions mitigated.
  • Throws methods now return Exception in case they need further inspection.
  • JJ.Framework.Exceptions.Core
  • ThrowIf method for guard statements to assert any condition.
  • Overload added for chainable NotNull assertion method.
  • JJ.Framework.Reflection.Core
  • Fix DynamicallyAccessedMembers annotation for code trimming on AccessorCore's target object auto-instantiation (AllCtors instead of just PublicCtors).
  • Add Assembly-related overloads.
  • JJ.Framework.PlatformCompatibility.Core
  • Fix Lock shim that was accidentally not thread-safe.
  • Add NotNullIfNotNull shim for nullable annotation support.
  • Shim for ProcessSupport.Kill with entireProcessTree arg (does not actually kill entire process tree, but prevents compiler errors).
  • JJ.Framework.SharedProject.Core
  • Improve reusable NoTrimReason strings, so they can be combined without redundancies with this syntax:
  • [TrimWarn(PropertyTypeAnd + ObjectGetType)]
  • The And-version includes a space separator and the non-And variant includes the DoWhatInstead.
  • DevOps:
  • Split Directory.Build.props into separate XML files / made modular.
  • Use .NET versions MSBuild convenience variables.
  • Add AutoPublish var for central conditions and the possibility to override (per project).
  • ClearCache calls new ClearMisc to wipe Azure Pipelines folders.
  • AzurePipelinesClearRetainFlags scripts helping to clean up locked Azure DevOps objects clearing excessive storage use.
  • RunTrimTest.bat now operates on current dir, not bat file dir.

2026-06-29 | 4.8/0.256 : RandomizerLegacy Move

+ Related Fixes

  • JJ.Framework.Mathematics.Legacy
  • Moved RandomizerLegacy class from .Core variant of project to .Legacy project.
  • Fully tested and now release as part of the .Legacy lib.
  • Expanded for coherence. And ported back to 2021 legacy branch.
  • (RandomizerLegacy is a 2021 version. Legacy projects contain code from 2015; Core projects code from 2025. Code from 2021 is somewhere in the middle. It made more sense to move those from .Core to .Legacy since the workflow around Legacy code is so much different than Core, that it makes more architectural sense to group them.)
  • JJ.Framework.IO.Core
  • Fix Mutex UnauthorizedAccess in Azure Pipelines.
  • For numbering file names (in highly concurrent situations).
  • Mutex created by other user, wouldn't be accessible to one in a different security context.
  • MutexSecurity specifying wider security access, so it can be used machine-wide as intended.
  • JJ.Framework.PlatformCompatibility.Core
  • OperatingSystemSupport.IsWindows(): a check for feature toggles (not present on all .NET version)
  • (Used for conditional MutexSecurity instantion.)
  • Added net462 target framework extra hardening.
  • NotNullIfNotNull retroactively added (accidentally not released last time).
  • JJ.Framework.Common.Core
  • GenericOverload / GenOvl:
  • Placeholder type for adding optional parameters to generic overloads, that would otherwise clash.
  • This type adds docs explaning the technique, and avoids further overload clashes, from chosing a different parameter type.

2026-07-02 | 4.9/0.257 : StreamHelperLegacy Move

  • JJ.Framework.IO.Legacy
  • Move StreamHelperLegacy from .Core variant of project to .Legacy variant
  • Port their tests from legacy branch to main
  • Tighten nullability checks.
  • JJ.Framework.IO.Core
  • Share NumberedFilePath/SafeFileStream Tests back and forth between legacy and main.
  • Mutex UnauthorizedAccess fixes for Azure Pipelines after introducing more tests.

2026-07-07 | 5.0/0.258 : Result Type Legacy Move

  • JJ.Framework.Business.Legacy
  • Result types.
  • Moved from .Core to the .Legacy project.
  • Removed JJ.Business.IO.Core project variant.
  • Full, meaningful test coverage, IntelliSense docs.
  • Tighter nullability, diagnostic texts.
  • JJ.Framework.IO.Core
  • SafeFileStream Mutex
  • Use Local namespace instead of Global (for per-user security)
  • Create with ACL (Access Control Descriptor) first, then fallback to without.
  • Refactor Mutex creation methods to reuse the same logic.
  • JJ.Framework.Logging.Core
  • Trace logging (alongside Console and Debug) for certain debugging scenarios.
  • JJ.Framework.PlatformCompatibility.Core
  • required keyword .NET 5 / .NET 6 support.

2026-07-08 | 5.1/0.259 : Result Type Rework

  • JJ.Framework.Business.Legacy
  • Success = false by default (previously true) improving compatibility and security.
  • Add Succesful and VoidResult aliases for Success and Result for compatibility.
  • Messages not separated by commas in diagnostics texts. Punctuation left up to the messages themselves.

💬 Feedback

Got feedback or questions? You can reach me here.