WizardWrx .NET API ReadMe
The notes in this file are a continuously updated story of major changes in the
libraries that comprise the WizardWrx .NET API. A companion document,
ChangeLog.md, gives a much more thorough accounting of the improvements and
bug fixes incorporated in each release.
Release Notes, 2020-10-18 10:56:24, Entire Library
This release completes alignment of the library collection with the SemVer version numbering scheme, and implements the Deterministic compiler switch throughout.
Nothing else of note has happened since
WizardWrx.AssemblyUtils was updated on
16 December 2019, the 249th birthday of Ludwing van Beethoven. Finishing the
implementation by the end of 2019 faded quickly as life intervened, and I was
becoming concerned that it might take until the master composer's 250th
Release Notes, 2019/12/16, WizardWrx.AssemblyUtils
This library gets the SemVer treatment, a new instance method on its
DependentAssemblies class, and the overloaded constructor on that
class finally works correctly in all respects.
Release Notes, 2019/12/16, WizardWrx.ASCIIInfo, WizardWrx.Core, WizardWrx.FormatStringEngine
This update implements two changes in the infrastructure of the WizardWrx .NET API libraries.
These libraries abandon NuGet packages as their means of consuming updates to sibling dependencies
WizardWrx.FormatStringEnginein favor of old-fashioned project references. Though consuming NuGet packages looks great on paper, it proved awkward in practice because everything stayed one release behind.
These libraries trade traditional 4-part version numbers for the industry standard 3-part SemVer numbering adopted for the NuGet Repository. This scheme improves version control by eliminating the time stamp generated for the fourth part by the asterisk, thereby making builds detrministic.
To date, these changes are implemented only for the core libraries, essentially WizardWrx.Common and WizardWrx.Core; the other two libraries listed above being dependencies of the core library. I expect to complete the transition before the end of calendar year 2019. The next update involves WizardWrx.AssemblyUtils, which is getting a new method that exposes a list that was previously kept private.
Release Notes, 2019/12/15, WizardWrx.Common.dll, Version 7.23.123
This update adds static method FormatIntegerLeftPadded to the NumericFormats class. This update also adopts the generally accepted SemVer version numbering scheme.
Release Notes, 2019/10/02, WizardWrx.Common.dll, Version 7.22.122
This upgrade affects only one library,
WizardWrx.Common.dll; although others
are updated with the new product version number, they are otherwise unchanged.
The changes in this library are confined to the public string resources, defined
.RESX file. The additions are listed in
Release Notes, 2019/06/11, WizardWrx AssemblyUtils.dll, Version 7.20.117
This build is a bug fix. I discovered that the iten number written into the
optional tab-delimited output file generated by
SortableManagedResourceItem.ListResourcesInAssemblyByName was always the
total item count, rather than the actual item number.
Although MSBuild created a new version of the test stand assembly, its code is unchanged.
Release Notes, 2019/06/10, Version 7.20
Only two of the ten libraries in this constellation have changes in this minor update that was driven primarily by the need to fix a bug.
The static class that defines the
FileInfo extension methods gets a bug fix,
which brought about the need for the update.
Previous testing overlooked the case when the file name from which the
instance that is fed into extension method
ShowFileDetails refers to a file
that does not exist. This is an issue because I overlooked the fact that the
Length property on the
FileInfo object throws a
Exception when the associated file does not exist, although other properties
return values of some kind, regardless of whether the file is present or
absent. Since a size of zero is a legitimate, and fairly commonplace, length
(size) of a file, this method reports -1, which is not. This is consistent with
the behavior of the time stamp properties, which report 1600/01/01 00:00:00 in
the absence of a file in the file system.
This update adds an optional parameter to one static method, and it corrects a documentation omission in another.
SortableManagedResourceItem.ListResourcesInAssemblyByNamegets an optional
StreamWriterargument that causes it to create a tab delimited list of the managed string resources in an assembly.
ReportGenerators.ListKeyAssemblyPropertiesshad lost the summary paragraph of its XML documentation, which is restored.
Release Notes, 2019/06/04, Version 7.19
This upgrade affects only one library,
WizardWrx.Core.dll; although others
are updated with the new product version number, they remain otherwise
unchanged. The changes in this library are confined to the
class, and consist of the following three new methods.
|Method Name||Method Goal|
|UnixLineEndings||Replace CR/LF pairs and bare CRs with bare LFs.|
|WindowsLineEndings||Replace bare LFs with CR/LF pairs.|
|OldMacLineEndings||Replace CR/LF pairs and bare LFs with bare CRs.|
There are literally no other changes in this update.
Release Notes, 2019/05/21
Version 7.18 is a maintenance release, which affects only one library,
WizardWrx.Core.dll, which got rushed into production without sufficient
testing. This release got the substantially more careful testing that I prefer
to give to everything. The companion NuGet package went out when I built the
release configuration of the whole library set.
Release Notes, 2019/05/21
The updates in this release revolve around two features in the core library,
WizardWrx.AssemblyUtils, a specialized library that
generates reports about assemblies. These are the only two libraries that have
The main improvement is a new extension method for
ShowFileDetails, which returns a formatted string containing selected
details about the file associated with the
System.IO.FileInfo object to
which it is applied. The method affords significant leeway to add or omit
properties, and the single format string upon which it is based is stored in the
library string resources.
WizardWrx.Common.dll is updated, the code is unchanged, since the
only change to the source code is a correction in one of the XML comments from
which the DocFX documentation pages are generated.
Beginning with this update, the accompanying NuGet packages include companion
symbol (program data base, or
.pdb) files, so that you can effortlessly step
into them in a debugger. As of this release, only the three libraries mentioned
herein include the symbol files. Others will get them as occasions arise to
perform other updates that merit generating new NuGet packages.
With this release, the two most actively updated libraries,
WizardWrx.Common.dll, automatically update their respective NuGet packages
when a new release build is created. A late addition,
also gets automated NuGet package pushes begining with this release.
The remaining seven libraries will eventually get the same treatment, but these three went first, because I needed to update them and immediately pull two of the three into another project.
Release Notes, 2019/05/05
The updates in this release revolve around a new method to apply pairs of strings, each composed of an original and a replacement value, to a string. Two versions exist, one which provides a place to stash the array, while the other is an extension method on the System.String class. The two new resource strings are incidental, though both are employed in the unlikely event that you feed an invalid array to the new methods.
Please see the change log for additional details.
Release Notes, 2019/05/03
Only the product build number changed, from 210 to 211, to account for the migration of all subsidiary projects to NuGet packages.
Each of the 10 libraries is in its own like-named NuGet package. For example,
the Nuget package that contains
following table lists the packages, along with their version numbers.
In addition to substituting NuGet packages throughout, a handful of errata in the XML documentation got fixed. Otherwise, the code is unchanged from the code that was first marked as version 7.15.
You can get everything with just three requests, made in the order listed next.
As proof that it works, unit test program DLLServices2TestStand.exe consumes all ten packages.
Release Notes, Version 7.15
This release introduces two new classes, both of which came into being to solve the harmless null reference exception mentioned below.
WizardWrx.RecoveredException is derived from System.Exception; its goal is to provide a convenient mechanism to report substantially everything that would be reported if an exception were thrown without incurring the overhead of throwing it. Such exceptions can be logged, as if they were real exceptions, and the log entry includes everything typically reported: message, method and assembly names, and a stack trace.
WizardWrx.Core.UnconfiguredDLLSettings is a mechaanism for gathering all DLL configuration settings that retained their hard coded default values because they were omitted from the DLL configuration file. Since the settings may be queried by methods that belong to different classes, which may even reside in different assemblies and namespaces, gathering them in one place requires the responsible class to be a singleton. This class organizes the data in a way that permits reporting on settings stored in two or more configuration files.
Other changes include a handful of new string constants for use as building blocks for other string constants, and elimination of a null reference exception that was silently caught and handled deep in the plumbing that manages DLL configuration settings. This exception was so subtle that the only evidence that it existed was in the output window of a Visual Studio debugger session. Since it was handled essentially at the point where it arose, its effect on processing went unnoticed. Since it never bubbled up, it was never reported in the event log.
Release Notes, Version 7.14
WizardWrx.MoreMath class moved to a dedicated assembly, so that its
target framework can change to support its use of another new class,
WizardWrx.ClassAndMethodDiagnosticInfo, which also gets its own assembly,
to report the name of a calling method without resorting to Reflection.
WizardWrx.ClassAndMethodDiagnosticInfo.dll, goes into a new
assembly because it requires the version of
that ships with version 4.5 of the Microsoft .NET Framework. All of the
above preserves the targeting of everything else to version 3.5 Client Profile
of the framework, because backwards compatibility matters a great deal,
especially when it is so easy to achieve without cost.
Release Notes, Version 7.13
EXACTLY_ONE_HUNDRED_MILLION_LONG, to meet an immediate requirement, along
EXACTLY_ONE_HUNDRED_MILLION, to more or
less complete the set of powers of ten from two to 9. All powers of ten in that
range sove one (ten million), for which there is no immediate need, are now
Release Notes, Version 7.12
New since version 7.11, out less than a week, are
MoreMath class, logical companions to
which first appeared in version 7.11. All three sport mechanisms to prevent the
DivideByZeroException exception. Though they still throw exceptions, an
ArgumentException exception takes its place, giving a few more clues about what
Fixes and improvements (mostly the latter) in version 7.11 are listed in the
Release_Notes_7.11.TXT. Since the
release notes were copied from the revision histories of the source files, they
went into a plain text file instead of a Markdown file. Nevertheless, you can
read it directly in the GitHub repository without explictly downloading it.
The most significant improvement in version 7.11 is the addition of
RenderEvenWhenNull to the
class, which defines extension methods on the
Another significant improvement is the addition of
in the new
WizardWrx.MoreMath class, defined in
faithfully implements the Gregorian year algorithm. This addition came about due
to an anticipated need for it in my current paying project, and is a port of code
that I wrote in ANSI C, and thoroughly tested about a decade ago.
Purpose of These Libraries
The purpose of these class libraries is to expedite development of applications that target any version of the Microsoft .NET Framework, from version 2.0 up. The classes in these libraries define numerous constants, most assigned to the base WizardWrx namespace, and utility classes, organized into subsidiary namespaces.
Up to version 7.12, my approach to versioning has been as follows.
AssemblyVersion tracks the build numbers as we go, and changes with every release, regardless of whether the release contains breaking changes. By design, breaking changes in my code are exteremely rare.
AssemblyFileVersion ties together all the assemblies in this API. This is achived by way of a spilt AssemblyInfo.cs class.
AssemblyInformationalVersion went unused.
Though this numbering scheme shall remain unchanged for the present, evaluating whether to continue or alter it is going onto the road map.
Using These Libraries
Since there are no name collisions, you may safely set references to all 6 namespaces in the same source module.
Detailed API documentation is at https://txwizard.github.io/WizardWrx_NET_API/.
For those who just want to use them, debug and release builds of the libraries and the unit test program are available as archives off the project root directory.
WizardWrx_NET_API_Binaries_Debug.7zis the debug build of the binaries.
WizardWrx_NET_API_Binaries_Release.7zis the release build of the binaries.
There is a DLL, PDB, and XML file for each library. To derive maximum benefit, including support for the Visual Studio managed code debugger and IntelliSense in the text editor, take all three.
Important: All but a couple of the libraries depend on one or more others;
if in doubt, check the manifest of the DLL(s) you plan to use. You can use
ILDASM.exe, which ships with the Microsoft .NET Framework SDKs.
ChangeLog.md for a cumulative history of changes, listed from newest to
oldest, beginning with version 7.1. Previous changes are meticulously documented
in the top of each source file.
For the most part, this constellation of class libraries evolves to acommodate needs as they arise in my development work. Nevertheless, I have a road map, and it has a few well-marked stops. As of Friday, 03 May 2019, a couple of the big ones, NuGet packaging, and configuration files that travel with their DLLs, are finally resolved.
Every library has a NuGet package, each of which has a working dependency chain. These dependencies mean that the whole API can be imported with just three requests to the NuGet Gallery.
Traveling DLL configuration files got fixed in MSBuild.
I've rearranged the remaining milestones to reflect new priorities.
Evaluate the current versioning protocol in light of lessons learned from recent studies of the matter.
AgedFileInfoand its companion
AgedFileInfoCollectioncould stand a companions that support other orderings of file lists, such as by size, type, or name.
The classes that process
FormatStringscould stand to be made more usable.
DigestFilesupport only MD5 and the SHAx message digest algorithms. While that covers the two most commonly used algorithms, I would like to cover others, and add HMAC digest authentication support. I have a native library, implemented in ANSI C, that supports HMAC, but I have yet to investigate what it would take to convert it.
ExceptionLoggershould define an interface to simplify replacing its
ReportExceptionmethods. Formatting of
ReportExceptionoutput could also stand to be a bit more flexible.
ReportHelperswere intended to be the foundation of an ambitious report generator for character-mode programs of the sort that are the lifeblood of systems software.
Though I created this library to meet my individual development needs, I have put a good bit of thought and care into its design. Moreover, since I will not live forever, and I want these libraries to outlive me, I would be honored to add contributions from others to it. My expectations are few, simple, easy to meet, and intended to maintain the consistency of the code base and its API.
Naming Conventions: I use Hungarian notation. Some claim that it has outlived its usefulness. I think it remains useful because it encodes data about the objects to which the names are applied that follows them wherever they go, and convey it without help from IntelliSense.
Coding Style: I have my editor set to leave spaces around every token. This spacing has helped me quicly spot misplaced puncuation, such as the right bracket that closes an array initializer that is in the wrong place, and it makes mathematical expressions easier to read and mentally parse.
Comments: I comment liberally and very deliberately. Of particular importance are the comments that I append to the bracket that closes a block. It does either or both of two things: link it to the opening statement, and document which of two paths an if statement is expected to follow most of the time. When blocks get nested two, three, or four deep, they really earn their keep.
Negative Conditions: I do my best to avoid them, because they almost always cause confusion. Astute observers will notice that they occur from time to time, because there are a few cases where they happen to be less confusing.
Array Initializers: Arrays that have more than a very few initializers, or that are initialized to long strings, are laid out as lists, with line comments, if necessary, that describe the intent of each item.
Format Item Lists: Lists of items that are paired with format items in calls to
Console.WriteLine, and their relatives, are laid out as arrays, even if there are too few to warrant one, and the comments show the corresponding format item in context. This helps ensure that the items are listed in the correct order, and that all format items are covered.
Symbolic Constants: I use symbolic constants to document what a literal value means in the context in which it appears, and to disambiguate tokens that are easy to confuse, suzh as
l(lower case L),
o(lower case O), literal spaces (1 and 2 spaces are common), underscores, the number
-1, and so forth. Literals that are widely applicable are defined in a set of classes that comprise the majority of the root
Argument Lists: I treat argument lists as arrays, and often comment each argument with the name of the paramter that it represents. These lists help guaranteeing that a long list of positional arguments is specified in the correct order, especially when several are of the same type (e. g., two or more integer arguments).
Triple-slash Comments: These go on everything, even private members and methods, so that everything supports IntelliSense, and it's easy to apply a tool (I use DocFX.) to generate reference documentation.
With respect to the above items, you can expect me to be a nazi, though I shall endeavor to give contributors a fair hearing when they have a good case. Otherwise, please exercise your imagination, and submit your pull requests. When I get NuGet packages implemented, I'll take care of rolling the contributions into the appropriate packages, and contributors will get prominent credit on the package page in the official public repository. If you skim the headnotes of the code, you'll see that I take great pains to give others credit when I icorporate their code into my projects, even to the point of disclaiming copyright or leaving their copyright notice intact. Along the same lines, the comments are liberally sprinkled with references to articles and Stack Overflow discussions that contributed to the work.