---
title: SAIF.NetCore.Common architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.Common
reference_type: package
---

# 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.

```mermaid
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.

```mermaid
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`](../../../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*.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)

> **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`
