---
title: SAIF.Framework.Common architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common
reference_type: package
---

# SAIF.Framework.Common architecture

`SAIF.Framework.Common` is a foundation utility library at the lowest tier of the SAIF .NET Framework 4 stack. It has zero outbound dependencies on other SAIF assemblies or third-party packages, which makes it safely referenceable by any layer above it. Its responsibility is to supply cross-cutting primitives: date/date-range semantics, string normalization and casing, validation result modelling, argument guards, sequence generation, serialization helpers, exception formatting, and logging contracts (Stage 1 analysis, "Responsibility boundary").

## Responsibilities
- Supply fail-fast argument/precondition guards (`Enforce`, `ValidatedNotNullAttribute`, `GenericExtensions.IsNull`/`IfNullThrow`) (Stage 1 analysis, "Functional groupings").
- Represent and reason about date intervals — validity, overlap, contiguity, open-endedness, membership — plus EDI/Julian date encoding (`IDateRange`, `DateRange`, `NullableDateRange`, `DateRangeExtensions`, `DateExtensions`, `DateMaker`, `Julian`) (Stage 1 analysis, "Functional groupings").
- Normalize and classify text: casing, truncation, character-class filtering, Unicode→ASCII folding, truthy-string parsing, decimal precision (`StringExtensions`, `StringUtilities`, `TitleCase`, `BooleanExtensions`, `NumericExtensions`) (Stage 1 analysis, "Functional groupings").
- Model validation outcomes and surface them as an exception (`IValidationResult`, `ValidationResult`, `IValidationFailure`, `ValidationFailure`, `SaifValidationException`) (Stage 1 analysis, "Functional groupings").
- Carry contextual (view-routing) exception information for a consuming presentation layer (`ContextException` and its four subclasses) (Stage 1 analysis, "Functional groupings").
- Provide in-memory monotonic sequence generators (`ISequenceGenerator<T>`, `SequenceGenerator<T>`, `Sequence`, `LongSequence`) (Stage 1 analysis, "Functional groupings").
- Provide JSON/XML serialization round-tripping, stream-to-byte-array conversion, MD5 hashing, and binary header search (`Serializer`, `GenericExtensions.ToJsonString`/`ToXmlString`, `DotNet40Extensions`, `FileExtensions`, `ByteExtensions`) (Stage 1 analysis, "Functional groupings").
- Define — but not implement — console/file logging contracts and format exception chains for logs (`ILogWriter`, `IConsoleLogService`, `LogType`, `ExceptionExtensions`) (Stage 1 analysis, "Functional groupings").
- Provide strongly-typed reflection helpers for property discovery and assignment (`Reflector`, `ExpressionExtensions`) (Stage 1 analysis, "Functional groupings").
- Provide empty marker contracts for downstream data-entity types (`IDataEntity`, `EntityBase<TEntity>`) (Stage 1 analysis, "Functional groupings").
- Parse ASP.NET MVC-style route segments from a `Uri` and split `DOMAIN\user` identity names (`UriExtensions`, `SecurityPrincipalExtensions`) (Stage 1 analysis, "Functional groupings").
- Fill LINQ/collection gaps: `ForEach`, `None`, `TakeFromEnd`, keyed `Distinct`, full/left outer joins, dictionary merge/upsert (`IEnumerableExtensions`, `DictionaryExtensions`) (Stage 1 analysis, "Functional groupings").

## Component boundaries
- Guard / precondition layer: `Enforce`, `ValidatedNotNullAttribute`, `GenericExtensions.IsNull`/`IfNullThrow` — fail-fast argument validation; throws `ArgumentNullException`/`ArgumentException`/caller-supplied exception types (Stage 1 analysis, "Functional groupings (layers within the library)").
- Date & date-range domain: `IDateRange`, `IDateRangeList`, `DateRange`, `NullableDateRange`, `DateRangeExtensions`, `DateExtensions`, `IComparableExtensions`, `DateMaker`, `Julian`, `DateRangeOverlapResult`, `IncludeComparisons`, `ContiguousOptions`, `OverlappingDateOptions` — represents and reasons about date intervals (Stage 1 analysis, same section).
- String & text normalization: `StringExtensions`, `StringUtilities`, `TitleCase`, `BooleanExtensions`, `NumericExtensions` — casing, truncation, character-class filtering, Unicode→ASCII folding, truthy-string parsing, decimal precision (Stage 1 analysis, same section).
- Validation modelling: `IValidationResult`, `ValidationResult`, `IValidationFailure`, `ValidationFailure`, `SaifValidationException` — accumulates property-level failures and surfaces them as an exception (Stage 1 analysis, same section).
- Contextual (view) exceptions: `ContextException` + 4 subclasses — carries a `TargetView` name and a `Model` payload so an MVC-style presentation layer can route to a specific error view* (Stage 1 analysis, same section).
- Sequence generation: `ISequenceGenerator<T>`, `SequenceGenerator<T>`, `Sequence`, `LongSequence` — in-memory monotonic counters (Stage 1 analysis, same section).
- Serialization: `Serializer`, `GenericExtensions.ToJsonString`/`ToXmlString`, `DotNet40Extensions`, `FileExtensions`, `ByteExtensions` — JSON (`JavaScriptSerializer`) and XML (`XmlSerializer`) round-tripping to/from files and strings; stream→byte[]; MD5 hashing; binary header search (Stage 1 analysis, same section).
- Diagnostics / logging contracts: `ILogWriter`, `IConsoleLogService`, `LogType`, `ExceptionExtensions` — define (but do not implement) console/file logging; format exception chains for logs (Stage 1 analysis, same section).
- Reflection helpers: `Reflector`, `ExpressionExtensions` — strongly-typed property discovery and assignment (Stage 1 analysis, same section).
- Entity markers: `IDataEntity`, `EntityBase<TEntity>` — empty marker contracts for downstream data-entity types (Stage 1 analysis, same section).
- Web/URL helpers: `UriExtensions`, `SecurityPrincipalExtensions` — parse ASP.NET MVC-style route segments from a `Uri`; split `DOMAIN\user` identity names (Stage 1 analysis, same section).
- Collection helpers: `IEnumerableExtensions`, `DictionaryExtensions` — LINQ gap-fillers: `ForEach`, `None`, `TakeFromEnd`, keyed `Distinct`, full/left outer joins, dictionary merge/upsert (Stage 1 analysis, same section).

## Interaction model
- The library is stateless and synchronous. It exposes no long-lived services, no I/O ports other than explicit file paths passed by the caller (`Serializer.LoadFromJson`, `SaveToXml`, `DotNet40Extensions.LoadFromJson`, and `ILogWriter.FilePath`, which is implemented elsewhere), and no network, database, or configuration access (Stage 1 analysis, "Data and control flow").
- All control flow is caller-driven: a consumer calls a static method or extension method, the method computes a result or throws, and returns (Stage 1 analysis, "Data and control flow").
- The only mutable state is the `CurrentValue` field held by a `SequenceGenerator<T>` instance and the collections held by a `ValidationResult` instance (Stage 1 analysis, "Data and control flow").
- There are no outbound cross-layer dependencies. Inbound, the library is designed to be consumed by SAIF application and component layers, evidenced by the ASP.NET MVC-shaped helpers (`UriExtensions.ControllerAndActionName` defaults to `"Home/Index"`, `ContextException.TargetView`), the console-logging contracts (`IConsoleLogService`), and the EDI/Julian date encoders that target mainframe file interchange formats* (Stage 1 analysis, "Cross-layer dependencies").
- `ILogWriter` and `IConsoleLogService` have no implementations in this library — they are contracts intended for consumers/other libraries to implement (Stage 1 analysis, "Interfaces (contracts)").

## Architecture diagram
The following diagram shows the library's internal functional groups, their intra-library couplings, the consuming applications outside this repository, and the .NET Framework 4.6.2 BCL surfaces they call into (Stage 1 analysis, "Architecture diagram").

```mermaid
flowchart TD
	subgraph Consumers["Consuming applications / components (outside this repo)"]
		C1["MVC / Web apps"]
		C2["Console batch apps"]
		C3["Component libraries"]
	end

	subgraph Lib["SAIF.Framework.Common (assembly)"]
		G["Guards<br>Enforce, GenericExtensions"]
		D["Date domain<br>IDateRange, DateRange,<br>DateRangeExtensions,<br>DateMaker, Julian, NullableDateRange"]
		S["Text<br>StringExtensions,<br>StringUtilities, TitleCase"]
		V["Validation<br>IValidationResult, ValidationResult,<br>ValidationFailure,<br>SaifValidationException"]
		X["Context exceptions<br>ContextException + subclasses"]
		Q["Sequences<br>ISequenceGenerator, SequenceGenerator,<br>Sequence, LongSequence"]
		Z["Serialization / bytes<br>Serializer, DotNet40Extensions,<br>FileExtensions, ByteExtensions"]
		L["Logging contracts<br>IConsoleLogService, ILogWriter, LogType"]
		R["Reflection<br>Reflector, ExpressionExtensions"]
		W["Web / identity<br>UriExtensions,<br>SecurityPrincipalExtensions"]
		E["Collections<br>IEnumerableExtensions,<br>DictionaryExtensions"]
	end

	subgraph BCL[".NET Framework 4.6.2 BCL"]
		B1["System / System.Core"]
		B2["System.Web.Extensions<br>JavaScriptSerializer"]
		B3["System.Xml<br>XmlSerializer"]
		B4["System.Security.Cryptography / Principal"]
	end

	C1 --> Lib
	C2 --> Lib
	C3 --> Lib

	S --> G
	D --> S
	E --> G
	W --> G
	V --> G
	Z --> B2
	Z --> B3
	Z --> B4
	Lib --> B1
```

## Sequence diagram
The following diagram shows the primary interaction pattern: a caller invokes a static method or extension method, which computes a result synchronously and returns or throws — the library holds no long-lived state beyond a `SequenceGenerator<T>` instance's `CurrentValue` or a `ValidationResult` instance's collections (Stage 1 analysis, "Data and control flow").

```mermaid
sequenceDiagram
	participant Caller
	participant Component as "SAIF.Framework.Common component<br>(static class / extension method)"
	Caller->>Component: Invoke static/extension method
	Component-->>Caller: Return computed result
	Component--xCaller: or throw an exception
```

## Design constraints
- The library declares zero `<ProjectReference>` and zero `<PackageReference>` entries, and its `.nuspec` declares no `<dependencies>`; it is a leaf with no in-repo or NuGet dependencies, which is what allows it to be safely referenced from any layer above it (Stage 1 analysis, "Internal (repository) dependencies", "NuGet / package dependencies").
- There is a circular namespace dependency between `SAIF.Common.Extensions` and `SAIF.Common.Utility`: `StringExtensions` calls `TitleCase`, and `TitleCase` calls back into `StringExtensions`/`IEnumerableExtensions`. This is legal in a single assembly but is a design coupling worth noting (Stage 1 analysis, "Intra-library coupling").
- `IncludeComparisons` is declared twice with identical members (once in `SAIF.Common`, once in `SAIF.Common.Extensions`), and `ContiguousOptions`/`OverlappingDateOptions` each have a duplicate/near-duplicate nested counterpart in `DateRangeExtensions`; a consumer importing both namespaces risks compile-time ambiguity or passing the wrong enum type* (Stage 1 analysis, "Duplicate and ambiguous public types").
- Namespace and folder layout are not aligned: `Classes/Enforce.cs` declares namespace `SAIF`; most `Classes/*.cs` declare `SAIF.Common`; only `ContextException.cs` and `NullableDateRange.cs` declare `SAIF.Common.Classes`; `Interfaces/` likewise splits between `SAIF.Common` and `SAIF.Common.Interfaces`* (Stage 1 analysis, "Namespaces", "Duplicate and ambiguous public types").
- `TitleCase` is `internal` while its sibling `StringUtilities` in the same namespace is `public`; the title-casing acronym/word lists are therefore reachable only through `StringExtensions.ToTitleCase` and cannot be extended by a consumer without a source change and rebuild* (Stage 1 analysis, "Duplicate and ambiguous public types").
- Two areas of behavior depend on ambient runtime state rather than configuration: `StringExtensions.ToProperCase`/`ToTitleCase` follow the current thread culture (`Thread.CurrentThread.CurrentCulture.TextInfo`), and several date operations (`DateExtensions.IsCurrentDate`/`IsFutureDate`/`IsPastDate`, `DateRangeExtensions.IsFutureRange`/`IsPastRange`, `Julian.GetYear`) depend on the server clock and time zone (Stage 1 analysis, "Ambient runtime state consumed").
- `Extensions/DotNet35Extensions.cs` exists on disk but has no `<Compile Include>` entry, so it is excluded from the compiled assembly even though the `.nuspec` ships it as source, meaning a consumer browsing package sources will see a type that does not exist at runtime* (Stage 1 analysis, "Build and packaging discrepancies", "nuspec contents").
- No automated test project exists under `Common/SAIF.Common/`, and `SAIF.Framework.Common.sln` contains only the one project (Stage 1 analysis, "Unknowns that cannot be resolved from this repository").

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

## Sources
- `Common/SAIF.Common/SAIF.Framework.Common.csproj`
- `SAIF.Framework.Common.sln`
- `Common/SAIF.Common/Classes/Enforce.cs`
- `Common/SAIF.Common/Extensions/StringExtensions.cs`
- `Common/SAIF.Common/Utility/TitleCase.cs`
- `Common/SAIF.Common/Extensions/DateRangeExtensions.cs`
- `Common/SAIF.Common/Classes/DateRange.cs`
- `Common/SAIF.Common/Extensions/ExceptionExtensions.cs`
- `Common/SAIF.Common/Interfaces/IConsoleLogService.cs`
- `Common/SAIF.Common/Interfaces/ILogWriter.cs`
