Skip to content

SAIF.NetCore.Common architecture

SAIF.NetCore.Common is a foundation-layer, general-purpose utility library of stateless static extension and helper classes, plus a small set of value/exception types for date ranges, validation results, and MVC-oriented context exceptions; it has zero SAIF and zero third-party package dependencies, and no library in this repository currently consumes it.

Responsibilities

  • Provide BCL-type extension methods for strings, dates, date ranges, dictionaries, enumerables, bytes, URIs, generics, comparables, expressions, numerics, and security principals (Extensions namespace).
  • Provide small static helper classes: DateMaker (EDI-style date strings), Enforce (argument guard clauses), Julian (Julian-date conversions), and Reflector (property-info reflection) (Helpers namespace).
  • Provide a validation-result model (ValidationResult, ValidationFailure) and a SaifValidationException for surfacing validation failures.
  • Provide MVC-oriented context exception types (ContextException and its four subclasses) whose TargetView values imply ASP.NET MVC view-routing intent in consuming applications*.
  • Provide DateRange/NullableDateRange value types and a sequence-generator type hierarchy (SequenceGenerator<T>, LongSequence, Sequence).
  • Provide shared enums (ContiguousOptions, DateRangeOverlapResult, IncludeComparisons, LogType, OverlappingDateOptions) for consumers, several of which duplicate nested enums defined on the extension classes themselves.

Component boundaries

  • Extensions: 15 static extension classes, each scoped to one BCL type or concern (string, date, date-range, dictionary, exception, expression, file, generic, comparable, enumerable, numeric, security-principal, URI, boolean, byte). No class holds mutable instance state.
  • Helpers: 4 public static helper classes plus one internal marker attribute (ValidatedNotNullAttribute) used only as a code-analysis hint on Enforce.ArgumentNotNull.
  • InternalUtility.TitleCase: an internal engine class that backs StringExtensions.ToTitleCase; it is not part of the public surface.
  • Types: 14 public types — exception hierarchies (ContextException and subclasses, SaifValidationException), value types (DateRange, NullableDateRange), an empty placeholder (EntityBase<TEntity>), and the sequence-generator hierarchy (SequenceGenerator<T>, LongSequence, Sequence).
  • Enums: 5 top-level enums, three of which (ContiguousOptions, IncludeComparisons, OverlappingDateOptions) are shadowed by functionally identical enums declared elsewhere in the assembly and are not bound by the library's own call sites*.
  • There is no DI, hosting, or configuration surface anywhere in this library: no IServiceCollection, IHostBuilder, IApplicationBuilder, IConfiguration, IOptions, environment-variable, or registry access exists in any of its 35 compiled files.

Interaction model

  • This library has no SAIF package dependency and is consumed by no library currently present in this repository; Architecture.md describes it as available for "any library (including contracts consumers) can use without pulling in the rest of the framework", but no current .csproj under src/ exercises that path*.
  • Internally, control flow is one-directional in most places but has one same-assembly cross-namespace cycle: Extensions classes call Helpers.Enforce.ArgumentNotNull for guard clauses, while Enforce's own members (IsNullOrWhiteSpace, IsNull, IsNullOrEmpty, IfNullThrow) call back into Extensions methods. This is a mutual dependency between namespaces inside one assembly, not a cross-package cycle.
  • Extensions.StringExtensions.ToTitleCase delegates to the internal InternalUtility.TitleCase engine, which in turn calls back into several Extensions members (IsNullOrEmpty, ToStringAll, IsIn, ToLower(string[]), TakeFromEnd, ToProperCase, ContainsOnlyNumericCharacters).
  • Extensions.DateRangeExtensions operates on Types.DateRange and calls IComparableExtensions.IsBetween and DateExtensions.IsMinOrMax; Types.NullableDateRange.GetOverlapState returns the Enums.DateRangeOverlapResult enum; Types.SaifValidationException carries a Types.ValidationResult, which carries a list of Types.ValidationFailure.
  • If a consuming library were to reference this package (per the README's stated intent and Architecture.md's "sometimes" wording), it would do so as a sibling NuGet reference alongside SAIF.NetCore.ServiceContracts, not as a replacement for it. This contradicts the README's own statement that the package "should never be a dependency of the NetCore.Services packages"; the discrepancy between the README and Architecture.md remains unresolved in available source materials.

Architecture diagram

The following diagram shows the internal namespace structure of this foundation-layer library and its (currently theoretical) relationship to the rest of the framework.

flowchart TD
    subgraph COMMON["SAIF.NetCore.Common (foundation layer)"]
        EXT["Extensions<br>(15 static extension classes)"]
        HLP["Helpers<br>(DateMaker, Enforce, Julian, Reflector)"]
        INT["InternalUtility.TitleCase<br>(internal)"]
        TYP["Types<br>(DateRange, ValidationResult,<br>ContextException, sequences)"]
        ENM["Enums<br>(5 top-level enums)"]
    end
    EXT -->|ArgumentNotNull| HLP
    HLP -->|guard predicates| EXT
    EXT -->|ToTitleCase| INT
    INT -->|string helpers| EXT
    EXT -->|DateRangeExtensions| TYP
    TYP -->|GetOverlapState result| ENM
    OTHER["Other SAIF.NetCore.* libraries<br>(no current consumer in this repo)"] -.->|NuGet ref, if adopted| COMMON

Sequence diagram

The following diagram shows a representative call sequence for the one documented cross-namespace cycle in this library: an Extensions call that delegates to Enforce and back.

sequenceDiagram
    participant Caller as Consumer code
    participant Ext as Extensions<br>(DictionaryExtensions)
    participant Enforce as Helpers.Enforce
    Caller->>Ext: UpdateOrAdd(dictionary, key, value)
    Ext->>Enforce: ArgumentNotNull(dictionary, "dictionary")
    Enforce->>Enforce: dictionary.IsNull()
    alt dictionary is null
        Enforce-->>Ext: throws ArgumentNullException
        Ext-->>Caller: propagates ArgumentNullException
    else dictionary is non-null
        Enforce-->>Ext: returns dictionary
        Ext->>Ext: ContainsKey(key)? set existing or Add(key, value)
        Ext-->>Caller: returns value
    end

Design constraints

  • No project references between libraries in this repository; this library takes zero package references of any kind, SAIF or third-party, consistent with its foundation-layer, zero-dependency position in Architecture.md.
  • Nearly every helper and extension class is static and stateless, with one documented exception: DateRange.Empty is a shared static instance whose BeginDate/EndDate have public setters, so any consumer that mutates it changes the value process-wide*.
  • Several members read DateTime.Now/DateTime.Today or the current thread culture directly (DateExtensions, DateRangeExtensions.IsFutureRange/IsPastRange, Julian.GetYear, StringExtensions.ToProperCase, DateRange.Parse/ToString), so their results depend on server clock, time zone, and locale.
  • DateRangeExtensions.IsOverLapping(IEnumerable<DateRange>) throws NullReferenceException for any input of 2 or more ranges because of an unconditional switch dereference on the first loop iteration, and any ==/!= comparison of a DateRange against null throws for the same underlying reason — both are known defects rather than intended behavior*.
  • The code shows heritage from a .NET Framework/VB.NET predecessor ([SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")]/[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "d")]-style attributes, a DateRange.cs header mentioning removed "SmartDate"/VB-style code, and a <RepositoryUrl> still pointing at the legacy TFS repository), which is reflected in some naming and design choices*.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common.csproj
  • src/SAIF.NetCore.Common/README.md
  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Extensions/ — DictionaryExtensions.cs, StringExtensions.cs, DateRangeExtensions.cs, IEnumerableExtensions.cs, UriExtensions.cs, IComparableExtensions.cs
  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Helpers/Enforce.cs
  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/InternalUtility/TitleCase.cs
  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Types/ — DateRange.cs, NullableDateRange.cs, ContextException.cs, SaifValidationException.cs, ValidationResult.cs, ValidationFailure.cs, EntityBase.cs, SequenceGenerator.cs, LongSequence.cs, Sequence.cs
  • src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Enums/ — ContiguousOptions.cs, DateRangeOverlapResult.cs, IncludeComparisons.cs, LogType.cs, OverlappingDateOptions.cs
  • Architecture.md