UA.Tenet 10.0.3

dotnet add package UA.Tenet --version 10.0.3
                    
NuGet\Install-Package UA.Tenet -Version 10.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="UA.Tenet" Version="10.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="UA.Tenet" Version="10.0.3" />
                    
Directory.Packages.props
<PackageReference Include="UA.Tenet" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add UA.Tenet --version 10.0.3
                    
#r "nuget: UA.Tenet, 10.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package UA.Tenet@10.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=UA.Tenet&version=10.0.3
                    
Install as a Cake Addin
#tool nuget:?package=UA.Tenet&version=10.0.3
                    
Install as a Cake Tool

UA.Tenet

NuGet Downloads

UA.Tenet is the core package of the Tenet framework. It gives a .NET solution one consistent application vocabulary: attributed services and agents, request and result contracts, reusable data helpers, explicit collection and query shaping, smart enums, and process-local messaging and events.

Why this package exists

Use UA.Tenet when you want a stable application core that stays independent from ASP.NET Core while still providing:

  • convention-based dependency injection for services and agents
  • configuration-first constructor activation for scalar settings
  • result-first workflows instead of exception-only happy paths
  • reusable JSON, XML, CSV, SQL, HTTP, and text helpers at integration boundaries
  • transportable filters, projections, and in-memory coordination primitives

If the host also needs HTTP endpoints, MVC, middleware, or Razor helpers, layer UA.Tenet.Web on top instead of replacing UA.Tenet.

Best fit

Use UA.Tenet when you are building:

  • shared libraries and domain or application layers
  • background or scheduled components modeled as Tenet agents
  • import, export, and integration-heavy services
  • API backends that need reusable filters, mapping helpers, or collection shaping
  • utility packages that should keep web concerns outside the core assembly

Package characteristics

  • Targets .NET 8, .NET 9, and .NET 10.
  • Ships XML documentation, SourceLink metadata, package symbols, and a package README.
  • Integrates with Microsoft.Extensions.Configuration.Abstractions and Microsoft.Extensions.Logging.Abstractions.

Core feature map

Area Main entry points What you get
Composition [TenetService], [TenetAgent], AddTenetServices(), AddTenetAgents(), ServiceBase<TModel, TContext>, AgentBase Convention-based DI registration, keyed services, service and agent lifetimes, configuration-first activation
Requests and results Request, Request<T>, Result, Result<T>, Command<T>, Observer, Singleton<TValue>, ResponsabilityChain Stable boundary contracts and explicit success or error outcomes
Data helpers Json, Xml, Csv, CsvSerializerOptions, Sql, Http, Text Serialization, ADO.NET helpers, HTTP calls, and text normalization
Collections and query shaping Any<T>, CanonicalSet, UniqueIndex<T>, EnumerableExtension, QueryableExtension, ConditionalExpression, RuleExpression, IMappable<TSource, TResult> Dynamic filtering, explicit projection semantics, and collection materializers such as ToAny() and ToCanonicalSet()
Coordination and richer models SmartEnum<T>, IMessageBroker, IEventBroker, InMemoryMessageBroker, InMemoryEventBroker Process-local messaging, events, and string-backed enum models

Installation

dotnet add package UA.Tenet

Quick start

Register Tenet services and agents

using UA.Tenet.Agents.Extensions;
using UA.Tenet.Services.Extensions;

builder.Services.AddTenetServices();
builder.Services.AddTenetAgents();

Implement a result-first Tenet service

using Microsoft.Extensions.Logging;
using UA.Tenet.Design;
using UA.Tenet.Services;

public sealed class CustomerModel
{
    public string? Name { get; set; }
}

public sealed class CustomerContext
{
}

[TenetService]
public sealed class CustomerService(CustomerContext context, ILogger<CustomerService> logger)
    : ServiceBase<CustomerModel, CustomerContext>(context, logger)
{
    public Result<string> CreateWelcomeMessage(Request<string> request)
    {
        if (string.IsNullOrWhiteSpace(request.Value))
            return new Result<string>(request).WithErrors("Validation", "Customer name is required.");

        Model = new CustomerModel { Name = request.Value };

        return new Result<string>(request)
        {
            Value = $"Tenet is ready for {Model.Name}."
        };
    }
}

Model an agent with configuration-first scalar activation

using Microsoft.Extensions.Logging;
using UA.Tenet.Agents;

public interface IInvoiceCleanupAgent
{
    Task RunAsync(CancellationToken cancellationToken);
}

[TenetAgent(Type = typeof(IInvoiceCleanupAgent), Lifetime = AgentLifetime.Singleton)]
public sealed class InvoiceCleanupAgent(
    int retentionDays,
    ILogger<InvoiceCleanupAgent> logger) : AgentBase, IInvoiceCleanupAgent
{
    public Task RunAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("Cleaning invoices older than {RetentionDays} days.", retentionDays);
        return Task.CompletedTask;
    }
}
{
  "InvoiceCleanupAgent": {
    "RetentionDays": 30
  }
}

Compose data helpers inside a service boundary

using System.Data.Common;
using UA.Tenet.Data;
using UA.Tenet.Design;
using UA.Tenet.Services;

[TenetService]
public sealed class CustomerImportService(DbConnection connection)
{
    public async Task<Result<int>> ImportAsync(Uri endpoint, CancellationToken cancellationToken)
    {
        await using Stream payload = await Http.GetStreamAsync(endpoint, cancellationToken);
        IEnumerable<CustomerRow>? rows = await payload.FromCsv<CustomerRow>(cancellationToken: cancellationToken);

        int imported = 0;

        foreach (CustomerRow row in rows ?? [])
        {
            if (string.IsNullOrWhiteSpace(row.ExternalCode))
                return new Result<int>().WithErrors("Validation", "ExternalCode is required.");

            await using DbCommand command = await connection.OpenCommand(
                "insert into Customers(ExternalCode, Name) values (@ExternalCode, @Name)");

            command.AddParameter("@ExternalCode", row.ExternalCode);
            command.AddParameter("@Name", row.Name);
            await command.ExecuteNonQueryAsync(cancellationToken);

            imported++;
        }

        return new Result<int>(imported);
    }
}

public sealed class CustomerRow
{
    public string? ExternalCode { get; set; }

    public string? Name { get; set; }
}

Important behavioral notes

  • Auto-registration scans assemblies already loaded into the current AppDomain.
  • Tenet activates attributed types through the first public constructor it finds, so one public constructor is the safest shape.
  • Scalar constructor parameters are read from configuration sections named after the target type before Tenet falls back to DI.
  • Result<T>.IsSuccessful is based on whether errors were collected, not on whether Value is non-null.
  • SmartEnum<T> normalizes names to uppercase and compares them case-insensitively.
  • EnumerableExtension and QueryableExtension use explicit-path projection semantics: direct node requests copy scalar members only, and deeper navigation shaping requires explicit nested paths.
  • The in-memory message and event brokers are process-local helpers, not durable infrastructure.

Relationship to UA.Tenet.Web

UA.Tenet is the core layer. Add UA.Tenet.Web when the solution needs HTTP composition, OpenAPI, MVC, minimal APIs, or Razor helpers.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on UA.Tenet:

Package Downloads
UA.Azure.Storage

UA.Azure.Storage provides a lightweight, efficient implementation for accessing Azure Storage Services (Blob, Queue, and Table) in .NET applications. Built on the Tenet Framework principles, it offers a simplified agent-based approach to interact with Azure Storage without heavy SDK dependencies.

UA.Tenet.Web

UA.Tenet.Web extends the Tenet Framework for ASP.NET Core applications. It provides a unified convention-based configuration combining the structure of Controller-based APIs with the performance of Minimal APIs, along with TagHelpers, view components, and web extensions.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.3 572 4/1/2026
10.0.2 144 4/1/2026
10.0.1 137 3/31/2026
10.0.0 130 3/26/2026
4.11.3 190 3/25/2026
Loading failed

See https://docs.uadevs.org/tenet/release-notes for release notes and documentation.