FractalDataWorks.Configuration
0.6.0-rc.1
dotnet add package FractalDataWorks.Configuration --version 0.6.0-rc.1
NuGet\Install-Package FractalDataWorks.Configuration -Version 0.6.0-rc.1
<PackageReference Include="FractalDataWorks.Configuration" Version="0.6.0-rc.1" />
<PackageVersion Include="FractalDataWorks.Configuration" Version="0.6.0-rc.1" />
<PackageReference Include="FractalDataWorks.Configuration" />
paket add FractalDataWorks.Configuration --version 0.6.0-rc.1
#r "nuget: FractalDataWorks.Configuration, 0.6.0-rc.1"
#:package FractalDataWorks.Configuration@0.6.0-rc.1
#addin nuget:?package=FractalDataWorks.Configuration&version=0.6.0-rc.1&prerelease
#tool nuget:?package=FractalDataWorks.Configuration&version=0.6.0-rc.1&prerelease
FractalDataWorks.Configuration
Generic multi-tenant hierarchical configuration provider for Microsoft.Extensions.Configuration.
Overview
FractalDataWorks.Configuration provides a flexible configuration system that separates data loading (Sources) from data processing (Provider). This enables integration with various storage backends while maintaining a consistent configuration interface.
Architecture:
- FdwConfigurationProvider - Generic provider that flattens and merges hierarchical configuration data
- ConfigurationBase<T> - Base class for strongly-typed configuration objects
- IGenericConfiguration - Interface for configuration metadata
- Configuration Sources - Pluggable data sources (SQL Server, JSON, etc.)
Key Features:
- Multi-Tenant Hierarchy - Four levels: DEFAULT, APPLICATION, TENANT, USER
- Source-Agnostic Provider - Works with any data source via delegate pattern
- Type-Safe Configurations - Generic base class for configuration inheritance
- Microsoft.Extensions.Configuration Integration - Standard .NET configuration system
Core Components
IGenericConfiguration - Base Interface
From IGenericConfiguration.cs:1-41:
namespace FractalDataWorks.Configuration;
using System;
/// <summary>
/// Base interface for all configuration objects in the FractalDataWorks framework.
/// Provides common properties for all configuration types.
/// </summary>
public interface IGenericConfiguration
{
/// <summary>
/// Gets the unique identifier for this configuration instance.
/// </summary>
Guid Id { get; set; }
/// <summary>
/// Gets the name of this configuration for lookup and display.
/// </summary>
string Name { get; set; }
/// <summary>
/// Gets the section name for this configuration in appsettings.
/// </summary>
string SectionName { get; }
}
/// <summary>
/// Generic configuration interface for type-safe configuration.
/// </summary>
/// <typeparam name="T">The concrete configuration type.</typeparam>
/// <remarks>
/// ServiceType discriminators are defined on domain-specific interfaces
/// (e.g., IConnectionConfiguration.ConnectionType, IAuthenticationConfiguration.AuthenticationType).
/// This allows each domain to use its own naming convention.
/// </remarks>
public interface IGenericConfiguration<T> : IGenericConfiguration
where T : IGenericConfiguration<T>
{
}
ConfigurationBase<T> - Typed Configuration Base Class
From ConfigurationBase.cs:1-65:
using System;
namespace FractalDataWorks.Configuration;
/// <summary>
/// Base class for all configuration types in the FractalDataWorks framework.
/// Provides common metadata properties for immutable configuration instances.
/// </summary>
/// <typeparam name="T">The derived configuration type (for type-safe chaining).</typeparam>
/// <remarks>
/// <para>
/// This base class provides:
/// <list type="bullet">
/// <item><description>Identity (Id, Name, SectionName)</description></item>
/// <item><description>Audit timestamps (CreatedAt, ModifiedAt)</description></item>
/// <item><description>Immutability via init-only properties</description></item>
/// </list>
/// </para>
/// <para>
/// Configuration discriminators are defined on domain-specific interfaces
/// (e.g., IConnectionConfiguration.ConnectionType).
/// </para>
/// </remarks>
public abstract class ConfigurationBase<T> : IGenericConfiguration<T>
where T : ConfigurationBase<T>
{
/// <summary>
/// Gets the unique identifier for this configuration instance.
/// </summary>
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// Gets the name of this configuration for lookup and display.
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// Gets the section name for this configuration in appsettings or database.
/// Must be overridden by derived classes.
/// </summary>
/// <example>"Email", "Database", "Notification"</example>
public abstract string SectionName { get; }
/// <summary>
/// Gets the timestamp when this configuration instance was created.
/// </summary>
public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
/// <summary>
/// Gets the timestamp when this configuration was last modified.
/// </summary>
public DateTime? ModifiedAt { get; init; }
}
FdwConfigurationProvider - Generic Provider
From FdwConfigurationProvider.cs:1-91:
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
namespace FractalDataWorks.Configuration;
/// <summary>
/// Generic multi-tenant configuration provider that flattens hierarchical configuration data.
/// Works with any IConfigurationSource that provides hierarchical data.
/// </summary>
public class FdwConfigurationProvider : ConfigurationProvider
{
private readonly IConfigurationSource _source;
private readonly Func<IDictionary<int, IDictionary<string, object>>> _loadHierarchy;
private readonly string _sectionName;
/// <summary>
/// Initializes a new instance of the provider.
/// </summary>
/// <param name="source">The configuration source.</param>
/// <param name="loadHierarchy">Function to load hierarchical data from the source.</param>
/// <param name="sectionName">Optional section name prefix for configuration keys.</param>
public FdwConfigurationProvider(
IConfigurationSource source,
Func<IDictionary<int, IDictionary<string, object>>> loadHierarchy,
string sectionName = "")
{
_source = source ?? throw new ArgumentNullException(nameof(source));
_loadHierarchy = loadHierarchy ?? throw new ArgumentNullException(nameof(loadHierarchy));
_sectionName = sectionName ?? string.Empty;
}
/// <summary>
/// Loads configuration data by calling the source's LoadHierarchy function
/// and flattening the result.
/// </summary>
public override void Load()
{
var hierarchy = _loadHierarchy();
Data = FlattenHierarchy(hierarchy);
}
/// <summary>
/// Flattens hierarchical configuration into a single dictionary.
/// Merges levels in order: DEFAULT (0) → APPLICATION (1) → TENANT (2) → USER (3).
/// Higher levels override lower levels.
/// </summary>
private Dictionary<string, string?> FlattenHierarchy(
IDictionary<int, IDictionary<string, object>> hierarchy)
{
var flattened = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
// Merge in order: DEFAULT (0) → APPLICATION (1) → TENANT (2) → USER (3)
for (int level = 0; level < 4; level++)
{
if (hierarchy.TryGetValue(level, out var levelData))
{
foreach (var kvp in levelData)
{
// Skip hierarchy metadata columns
if (IsMetadataColumn(kvp.Key))
{
continue;
}
// Add with optional section prefix
var key = string.IsNullOrEmpty(_sectionName)
? kvp.Key
: $"{_sectionName}:{kvp.Key}";
flattened[key] = kvp.Value?.ToString() ?? string.Empty;
}
}
}
return flattened;
}
/// <summary>
/// Determines if a column is metadata that should be excluded from configuration.
/// </summary>
private static bool IsMetadataColumn(string columnName)
{
return columnName switch
{
"Id" or "Level" or "TenantId" or "UserId" or "CreatedAt" or "ModifiedAt" => true,
_ => false
};
}
}
Hierarchical Multi-Tenant Configuration
The configuration system supports a 4-level hierarchy that allows progressive overriding:
| Level | Name | Purpose | Example Use Case |
|---|---|---|---|
| 0 | DEFAULT | System-wide defaults | Factory defaults for all tenants |
| 1 | APPLICATION | Application-level settings | Environment-specific (Dev/Staging/Prod) |
| 2 | TENANT | Tenant-specific overrides | Per-customer customization |
| 3 | USER | User-specific settings | Individual user preferences |
Merge Behavior:
- Values are merged from level 0 → 1 → 2 → 3
- Higher-level values override lower-level values
- Only non-metadata columns are included in the final configuration
Metadata Columns (Excluded):
Id- Configuration row identifierLevel- Hierarchy level (0-3)TenantId- Tenant identifier (null for levels 0-1)UserId- User identifier (null for levels 0-2)CreatedAt- Timestamp when createdModifiedAt- Timestamp when modified
Creating Configurations
Example: MsSql Connection Configuration
From MsSqlConnectionConfiguration.cs:43-143:
[ManagedConfiguration(
Schema = "cfg",
TableName = "MsSqlConnection",
Parent = nameof(ConnectionConfigurationBase<MsSqlConnectionConfiguration>),
ServiceCategory = "Connection",
ServiceType = "MsSql")]
public partial class MsSqlConnectionConfiguration : ConnectionConfigurationBase<MsSqlConnectionConfiguration>
{
/// <summary>
/// Gets the connection type name. Always returns "MsSql" for SQL Server connections.
/// </summary>
public override string ConnectionType => "MsSql";
/// <summary>
/// Gets the configuration section name for this connection.
/// </summary>
public override string SectionName => string.IsNullOrEmpty(Name) ? "Connections" : $"Connections:{Name}";
#region SQL Server Specific Properties
/// <summary>
/// Gets or sets the SQL Server hostname or IP address.
/// </summary>
public string Server { get; set; } = "localhost";
/// <summary>
/// Gets or sets the database name.
/// </summary>
public string Database { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the SQL Server port. Default is 1433.
/// </summary>
public int Port { get; set; } = 1433;
/// <summary>
/// Gets or sets the command timeout in seconds.
/// </summary>
public int CommandTimeoutSeconds { get; set; } = 30;
/// <summary>
/// Gets or sets the connection timeout in seconds.
/// </summary>
public int ConnectionTimeoutSeconds { get; set; } = 15;
/// <summary>
/// Gets or sets the default schema to use for operations.
/// </summary>
public string DefaultSchema { get; set; } = "dbo";
#endregion
}
Configuration Sources
Configuration sources implement IConfigurationSource and are responsible for querying the data store and providing configuration data.
MsSqlConfigurationSource
From MsSqlConfigurationSource.cs:23-65:
/// <summary>
/// SQL Server configuration source using FractalDataWorks DataCommands.
/// Reads configuration from cfg.* tables and provides it to IConfiguration.
/// </summary>
public sealed class MsSqlConfigurationSource : IConfigurationSource
{
/// <summary>
/// Gets or sets the data connection to the configuration database.
/// </summary>
public IDataConnection? Connection { get; set; }
/// <summary>
/// Gets or sets the service provider for resolving dependencies.
/// </summary>
public IServiceProvider? ServiceProvider { get; set; }
/// <summary>
/// Gets or sets the section name prefix for configuration keys.
/// </summary>
public string SectionName { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the service category filter (e.g., "Connection", "DataStore").
/// </summary>
public string? ServiceCategory { get; set; }
/// <summary>
/// Gets or sets the tenant ID for multi-tenant configuration.
/// </summary>
public string? TenantId { get; set; }
/// <summary>
/// Gets or sets the user ID for user-specific configuration.
/// </summary>
public string? UserId { get; set; }
/// <inheritdoc/>
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new MsSqlConfigurationProvider(this);
}
}
Available Sources
- FractalDataWorks.Configuration.MsSql - SQL Server source using DataCommands
See individual source packages for usage examples.
Usage with Microsoft.Extensions.Configuration
Basic Setup with IOptions
From ConfigurationIntegrationTests.cs:18-59:
// Arrange: Setup in-memory configuration
var configData = new Dictionary<string, string?>
{
["TestConnection:Name"] = "TestConnection",
["TestConnection:ConnectionString"] = "Server=localhost;Database=Test;",
["TestConnection:Timeout"] = "30"
};
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(configData)
.Build();
var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(configuration);
// Configure options binding for test configuration
services.Configure<TestConnectionConfiguration>(
configuration.GetSection("TestConnection"));
var serviceProvider = services.BuildServiceProvider();
// Act: Resolve configuration from DI
var options = serviceProvider.GetRequiredService<IOptions<TestConnectionConfiguration>>();
var config = options.Value;
// Assert: Configuration loaded correctly
config.Name.ShouldBe("TestConnection");
config.ConnectionString.ShouldBe("Server=localhost;Database=Test;");
config.Timeout.ShouldBe(30);
Using IOptionsSnapshot for Scoped Configuration
From ConfigurationIntegrationTests.cs:64-109:
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(configData)
.Build();
var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(configuration);
// Configure options binding for scoped snapshot
services.Configure<TestConnectionConfiguration>(
configuration.GetSection("TestConnection"));
var serviceProvider = services.BuildServiceProvider();
// Create scope and resolve IOptionsSnapshot
using var scope = serviceProvider.CreateScope();
var snapshot = scope.ServiceProvider
.GetRequiredService<IOptionsSnapshot<TestConnectionConfiguration>>();
var config = snapshot.Value;
// IOptionsSnapshot reloads configuration per scope
// In production with database-backed config, values could differ per scope
Architecture Principles
1. Separation of Concerns
Source Responsibilities:
- Connect to data store (SQL Server, JSON file, etc.)
- Execute queries/reads
- Transform raw data into configuration key-value pairs
- Handle connection/query errors
Provider Responsibilities:
- Receive hierarchy data via delegate
- Flatten multi-level structure
- Merge levels in correct order
- Filter metadata columns
- Apply section name prefixes
2. Delegate Pattern
The provider accepts a Func<IDictionary<int, IDictionary<string, object>>> delegate, allowing the source to control data loading while the provider handles processing. See the FdwConfigurationProvider implementation above for the actual pattern.
3. No Repository Pattern
Sources directly query the data store without an additional repository abstraction. This keeps the architecture simple and follows the single responsibility principle.
Example: Multi-Tenant Email Configuration
Database Schema
CREATE TABLE EmailConfiguration
(
Id INT IDENTITY(1,1) PRIMARY KEY,
Level INT NOT NULL, -- 0=DEFAULT, 1=APP, 2=TENANT, 3=USER
TenantId NVARCHAR(50) NULL, -- NULL for levels 0-1
UserId NVARCHAR(50) NULL, -- NULL for levels 0-2
SmtpHost NVARCHAR(100),
SmtpPort INT,
Username NVARCHAR(100),
Password NVARCHAR(255),
EnableSsl BIT,
TimeoutSeconds INT,
CreatedAt DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
ModifiedAt DATETIME2 NULL
);
Sample Data
-- Level 0: DEFAULT - System-wide defaults
INSERT INTO EmailConfiguration (Level, SmtpHost, SmtpPort, EnableSsl, TimeoutSeconds)
VALUES (0, 'smtp.gmail.com', 587, 1, 30);
-- Level 1: APPLICATION - Production environment settings
INSERT INTO EmailConfiguration (Level, SmtpHost, SmtpPort)
VALUES (1, 'smtp.company.com', 25);
-- Level 2: TENANT - Tenant-specific override
INSERT INTO EmailConfiguration (Level, TenantId, SmtpHost, Username, Password)
VALUES (2, 'acme-corp', 'smtp.acme.com', 'noreply@acme.com', 'encrypted-password');
-- Level 3: USER - User preference
INSERT INTO EmailConfiguration (Level, TenantId, UserId, TimeoutSeconds)
VALUES (3, 'acme-corp', 'john.doe', 60);
Result After Merge
For TenantId = "acme-corp" and UserId = "john.doe":
{
"Email:SmtpHost": "smtp.acme.com", // From TENANT (level 2)
"Email:SmtpPort": "25", // From APPLICATION (level 1)
"Email:Username": "noreply@acme.com", // From TENANT (level 2)
"Email:Password": "encrypted-password", // From TENANT (level 2)
"Email:EnableSsl": "True", // From DEFAULT (level 0)
"Email:TimeoutSeconds": "60" // From USER (level 3)
}
Installation
<PackageReference Include="FractalDataWorks.Configuration" />
<PackageReference Include="FractalDataWorks.Configuration.MsSql" />
Dependencies
- FractalDataWorks.Abstractions - Contains
IGenericConfigurationinterface - Microsoft.Extensions.Configuration - .NET configuration system
- Microsoft.Extensions.Configuration.Abstractions - Configuration abstractions
Best Practices
- Use ConfigurationBase<T> for strongly-typed configurations
- Override SectionName to match your configuration section naming convention
- Leverage the hierarchy - put shared defaults at DEFAULT level, tenant customizations at TENANT level
- Use metadata wisely - Id, Name, CreatedAt, ModifiedAt are automatically excluded from configuration values
- Keep sources focused - Sources should only handle data loading, not processing
- Test multi-tenant scenarios - Verify different TenantId/UserId combinations produce correct merged values
OptionsLoader TypeCollection
The OptionsLoaderTypes TypeCollection provides three loader implementations that wrap the Microsoft.Extensions.Options interfaces.
From OptionsLoaderTypes.cs:1-36:
/// <summary>
/// Type collection for options loader types.
/// Source generator creates compile-time discovery of all options loader implementations.
/// </summary>
/// <remarks>
/// <para>
/// Available options loaders (discovered via [TypeOption] attribute):
/// </para>
/// <list type="bullet">
/// <item><description><b>Singleton</b>: IOptions, loaded once at startup (best for static configuration)</description></item>
/// <item><description><b>Scoped</b>: IOptionsSnapshot, reloaded per scope/request (best for multi-tenant scenarios)</description></item>
/// <item><description><b>Reloadable</b>: IOptionsMonitor, supports hot reload with change notifications (best for runtime configuration changes)</description></item>
/// </list>
/// </remarks>
[TypeCollection(typeof(OptionsLoaderBase), typeof(IOptionsLoader), typeof(OptionsLoaderTypes))]
public sealed partial class OptionsLoaderTypes : TypeCollectionBase<OptionsLoaderBase, IOptionsLoader>
{
}
Configuration Source to OptionsLoader Mapping
| Configuration Source | Recommended OptionsLoader | Reason |
|---|---|---|
| appsettings.json (static) | SingletonOptionsLoader |
Config loaded once at startup |
| appsettings.json (file-watched) | ReloadableOptionsLoader |
Supports hot reload when file changes |
| Database (MsSqlConfigurationSource) | ReloadableOptionsLoader |
Detects config changes via polling/change tracking |
| Environment variables | SingletonOptionsLoader |
Env vars typically do not change during runtime |
| Multi-tenant configuration | ScopedOptionsLoader |
Reloads per tenant/request scope |
SingletonOptionsLoader
From SingletonOptionsLoader.cs:23-50:
/// <summary>
/// Options loader that uses IOptions for singleton configuration loading.
/// Configuration is loaded once at application startup and cached for the lifetime of the application.
/// </summary>
/// <remarks>
/// Use this when:
/// - Configuration doesn't change at runtime
/// - You want the best performance (no reload overhead)
/// - Configuration is the same for all scopes/requests
///
/// Does NOT support:
/// - Hot reload / configuration changes at runtime
/// - Per-scope/per-request configuration
/// </remarks>
[TypeOption(typeof(OptionsLoaderTypes), "Singleton")]
public sealed class SingletonOptionsLoader : OptionsLoaderBase
{
public SingletonOptionsLoader() : base(1, "Singleton") { }
public override string OptionsInterfaceName => "IOptions";
public override bool SupportsHotReload => false;
public override string CurrentValueAccessor => ".Value";
public override bool RequiresDisposable => false;
}
ScopedOptionsLoader
From ScopedOptionsLoader.cs:27-47:
/// <summary>
/// Options loader that uses IOptionsSnapshot for scoped configuration loading.
/// Configuration is reloaded at the beginning of each scope/request.
/// </summary>
/// <remarks>
/// Use this when:
/// - Configuration might differ per scope/request (multi-tenant scenarios)
/// - You want configuration reloading but don't need instant hot reload
/// - Services are registered as Scoped
///
/// Does NOT support:
/// - Instant hot reload within a scope
/// - Singleton services (scoped options can't be injected into singletons)
/// </remarks>
[TypeOption(typeof(OptionsLoaderTypes), "Scoped")]
public sealed class ScopedOptionsLoader : OptionsLoaderBase
{
public ScopedOptionsLoader() : base(2, "Scoped") { }
public override string OptionsInterfaceName => "IOptionsSnapshot";
public override bool SupportsHotReload => false;
public override string CurrentValueAccessor => ".Value";
public override bool RequiresDisposable => false;
}
ReloadableOptionsLoader
From ReloadableOptionsLoader.cs:28-48:
/// <summary>
/// Options loader that uses IOptionsMonitor for reloadable configuration with hot reload support.
/// Configuration can be reloaded at runtime with change notifications.
/// </summary>
/// <remarks>
/// Use this when:
/// - Configuration can change at runtime (database-backed config, config file changes)
/// - You need instant hot reload without restarting the application
/// - You want to respond to configuration changes via OnChange notifications
///
/// Requires:
/// - IDisposable implementation to clean up OnChange subscriptions
/// </remarks>
[TypeOption(typeof(OptionsLoaderTypes), "Reloadable")]
public sealed class ReloadableOptionsLoader : OptionsLoaderBase
{
public ReloadableOptionsLoader() : base(3, "Reloadable") { }
public override string OptionsInterfaceName => "IOptionsMonitor";
public override bool SupportsHotReload => true;
public override string CurrentValueAccessor => ".CurrentValue";
public override bool RequiresDisposable => true;
}
Using OptionsLoader with ServiceTypes
ServiceTypes accept an OptionsLoaderBase parameter in their constructor:
From ServiceTypeBase.cs:260-270:
protected ServiceTypeBase(
string name,
string sectionName,
string displayName,
string description,
OptionsLoaderBase optionsLoader,
string? category = null)
: base(Id, name, sectionName, displayName, description, category)
{
OptionsLoader = optionsLoader ?? throw new ArgumentNullException(nameof(optionsLoader));
}
Recommendation: Use the simplest loader that meets your requirements. If configuration does not change at runtime, use SingletonOptionsLoader.
Related Packages
- FractalDataWorks.Configuration.MsSql - SQL Server configuration source
- FractalDataWorks.Configuration.Abstractions - Configuration interfaces and base classes
- FractalDataWorks.Abstractions - Core interfaces including IGenericConfiguration
See Also
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- FractalDataWorks.Abstractions (>= 0.6.0-rc.1)
- FractalDataWorks.Collections (>= 0.6.0-rc.1)
- FractalDataWorks.Configuration.Abstractions (>= 0.6.0-rc.1)
- FractalDataWorks.Results (>= 0.6.0-rc.1)
- Microsoft.Extensions.Configuration (>= 10.0.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Options (>= 10.0.0)
-
net10.0
- FractalDataWorks.Abstractions (>= 0.6.0-rc.1)
- FractalDataWorks.Collections (>= 0.6.0-rc.1)
- FractalDataWorks.Configuration.Abstractions (>= 0.6.0-rc.1)
- FractalDataWorks.Results (>= 0.6.0-rc.1)
- Microsoft.Extensions.Configuration (>= 10.0.1)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.1)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Options (>= 10.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FractalDataWorks.Configuration:
| Package | Downloads |
|---|---|
|
FractalDataWorks.Configuration.MsSql
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
GitHub repositories
This package is not used by any popular GitHub repositories.