FractalDataWorks.Collections
0.6.0-rc.1
dotnet add package FractalDataWorks.Collections --version 0.6.0-rc.1
NuGet\Install-Package FractalDataWorks.Collections -Version 0.6.0-rc.1
<PackageReference Include="FractalDataWorks.Collections" Version="0.6.0-rc.1" />
<PackageVersion Include="FractalDataWorks.Collections" Version="0.6.0-rc.1" />
<PackageReference Include="FractalDataWorks.Collections" />
paket add FractalDataWorks.Collections --version 0.6.0-rc.1
#r "nuget: FractalDataWorks.Collections, 0.6.0-rc.1"
#:package FractalDataWorks.Collections@0.6.0-rc.1
#addin nuget:?package=FractalDataWorks.Collections&version=0.6.0-rc.1&prerelease
#tool nuget:?package=FractalDataWorks.Collections&version=0.6.0-rc.1&prerelease
FractalDataWorks.Collections
Source-generated type collections for cross-project extensible type discovery in the FractalDataWorks ecosystem. Provides compile-time type safety using FrozenDictionary (on .NET 8+) or ImmutableDictionary (on netstandard2.0) for type collections where downstream developers can add their own options.
Overview
The Collections system provides cross-project type discovery for extensible type systems where:
- Collections are placed in abstractions projects for discoverability
- Base Types are in concrete projects and MUST inherit from
TypeOptionBase<TKey, T>whereTKey : IEquatable<TKey> - Interfaces define the contract and MUST extend
ITypeOption<TKey, T> - Type Options can be added by downstream developers in any project
- TypeCollections themselves ARE TypeOptions with
intIds (hash of collection name), enabling parent-child nesting viaTypeOption
Key Architecture Insight: Two Key Types
TypeCollections have TWO separate key types:
Collection's Own Id (always
int) - Used when the collection itself is treated as a TypeOption- Enables parent-child collections via
TypeOption - Auto-generated from collection type name hash
- Enables parent-child collections via
TypeOptions' Keys (
TKey) - Used for looking up TypeOptions within the collection- Extracted from base type's
ITypeOption<TKey, T>implementation - Can be
int,string,Guid, or anyIEquatable<TKey>type - Example:
CommandTypeBase : ITypeOption<int, CommandTypeBase>→ TKey =int
- Extracted from base type's
Required Architecture Components
CRITICAL: All TypeCollections MUST follow this 4-component pattern. Missing any component will cause compilation failures or runtime issues.
1. Interface (in Abstractions Project)
REQUIRED: Must extend ITypeOption<TKey, TBase>
From IConnectionState.cs:1-10:
using FractalDataWorks.Collections;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// Interface for connection states.
/// </summary>
public interface IConnectionState : ITypeOption<int, ConnectionStateBase>
{
}
Why ITypeOption<TKey, TBase> Format:
TKey(first parameter) =int- The key type for dictionary lookupsTBase(second parameter) =ConnectionStateBase- The base type (CRTP pattern)
2. Base Class (in Concrete/Abstractions Project)
REQUIRED: Must inherit from TypeOptionBase<TKey, T> AND implement the interface
From ConnectionStateBase.cs:1-22:
using FractalDataWorks.Collections;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// Base class for connection states in the FractalDataWorks framework.
/// </summary>
/// <remarks>
/// Connection states help track the lifecycle of external connections and enable
/// proper connection management, pooling, and error handling throughout the framework.
/// </remarks>
public abstract class ConnectionStateBase : TypeOptionBase<int, ConnectionStateBase>, IConnectionState
{
/// <summary>
/// Initializes a new instance of the <see cref="ConnectionStateBase"/> class.
/// </summary>
/// <param name="id">The unique identifier for this connection state.</param>
/// <param name="name">The name of this connection state.</param>
protected ConnectionStateBase(int id, string name) : base(id, name)
{
}
}
Why TypeOptionBase<TKey, T> is Required:
- Provides
TKey Idproperty (e.g.,int Id) that source generator uses - Provides
string Nameandstring Categoryproperties - Ensures consistent behavior across all TypeCollections
- Enables dictionary lookups:
FrozenDictionary<TKey, TBase>(.NET 8+) orImmutableDictionary<TKey, TBase>(netstandard2.0) - Supports
[TypeLookup]attributes for alternate keys (e.g.,[TypeLookup("ById")],[TypeLookup("ByName")])
Flexible Key Types:
int- Most common (IDs, enums)string- Named lookups (command names, identifiers)Guid- Unique identifiers- Any type implementing
IEquatable<TKey>
3. TypeCollection (in Abstractions Project)
REQUIRED: Must be marked with [TypeCollection] and extend TypeCollectionBase<TBase, TInterface>
CRITICAL: NO TKey parameter on TypeCollectionBase - it's extracted from the base type!
From ConnectionStates.cs:1-16:
using FractalDataWorks.Collections;
using FractalDataWorks.Collections.Attributes;
using FractalDataWorks.Services.Connections.Abstractions;
using System.Diagnostics.CodeAnalysis;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// Collection of connection states.
/// </summary>
[ExcludeFromCodeCoverage]
[TypeCollection(typeof(ConnectionStateBase), typeof(IConnectionState), typeof(ConnectionStates))]
public abstract partial class ConnectionStates : TypeCollectionBase<ConnectionStateBase, IConnectionState>
{
}
How TKey is Discovered:
- Generator looks at
ConnectionStateBase - Finds
ConnectionStateBase : TypeOptionBase<int, ConnectionStateBase> - Extracts
TKey = intfrom theITypeOption<int, ...>implementation - Generates:
FrozenDictionary<int, ConnectionStateBase> _all
TypeCollection Inherits from TypeOptionBase:
TypeCollectionBase<TBase, TInterface>inherits fromTypeOptionBase<int, TypeCollectionBase<TBase, TInterface>>- Collections have
int Id(hash of collection name) andstring Name - This enables collections to be nested via
TypeOption(parent-child pattern)
TypeCollection Attribute Parameters:
typeof(ConnectionStateBase)- The base class to discover (must inherit from TypeOptionBase<TKey, T>)typeof(IConnectionState)- The interface type to return (must extend ITypeOption<TKey, T>)typeof(ConnectionStates)- This collection class
4. Concrete TypeOptions (in Any Project)
REQUIRED: Must be marked with [TypeOption] and inherit from the base class
From OpenConnectionState.cs:1-11:
using FractalDataWorks.Collections.Attributes;
using System.Diagnostics.CodeAnalysis;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// The connection is open and ready for use.
/// </summary>
[ExcludeFromCodeCoverage]
[TypeOption(typeof(ConnectionStates), "Open")]
public sealed class OpenConnectionState() : ConnectionStateBase(3, "Open");
TypeOption Attribute Parameters:
typeof(ConnectionStates)- The collection type this option belongs to"Open"- Display name (becomes property name:ConnectionStates.Open)
Complete Working Example: Connection States
This example shows the EXACT pattern that MUST be followed. All code is from actual source files in the FractalDataWorks codebase.
TypeOptions in the Connection States Collection
The following TypeOptions are defined in the FractalDataWorks.Services.Connections.Abstractions project:
From ClosedConnectionState.cs:1-11:
using FractalDataWorks.Collections.Attributes;
using System.Diagnostics.CodeAnalysis;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// The connection is closed.
/// </summary>
[ExcludeFromCodeCoverage]
[TypeOption(typeof(ConnectionStates), "Closed")]
public sealed class ClosedConnectionState() : ConnectionStateBase(6, "Closed");
From OpeningConnectionState.cs:1-11:
using FractalDataWorks.Collections.Attributes;
using System.Diagnostics.CodeAnalysis;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// The connection is currently being opened.
/// </summary>
[ExcludeFromCodeCoverage]
[TypeOption(typeof(ConnectionStates), "Opening")]
public sealed class OpeningConnectionState() : ConnectionStateBase(2, "Opening");
From ExecutingConnectionState.cs:1-11:
using FractalDataWorks.Collections.Attributes;
using System.Diagnostics.CodeAnalysis;
namespace FractalDataWorks.Services.Connections.Abstractions;
/// <summary>
/// The connection is currently executing an operation.
/// </summary>
[ExcludeFromCodeCoverage]
[TypeOption(typeof(ConnectionStates), "Executing")]
public sealed class ExecutingConnectionState() : ConnectionStateBase(4, "Executing");
Generated API Usage
The source generator creates lookup methods and static properties. From the generated code in ConnectionStates.TypeCollection.g.cs:
// Static properties - get concrete types directly
OpenConnectionState open = ConnectionStates.Open;
ClosedConnectionState closed = ConnectionStates.Closed;
ExecutingConnectionState executing = ConnectionStates.Executing;
// Lookup by Id - returns interface type, Empty if not found
IConnectionState byId = ConnectionStates.ById(3); // Returns Open
IConnectionState notFound = ConnectionStates.ById(999); // Returns Empty
// Lookup by Name - returns interface type, Empty if not found
IConnectionState byName = ConnectionStates.ByName("Executing"); // Returns Executing
// Collection access - returns all registered TypeOptions
IReadOnlyCollection<IConnectionState> all = ConnectionStates.All();
// Empty sentinel for failed lookups
IConnectionState empty = ConnectionStates.Empty;
Architecture Pattern Overview
Project Structure:
┌─────────────────────────────────────────────────────────────────────────┐
│ Abstractions Project │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 1. IConnectionState : ITypeOption<int, ConnectionStateBase> │ │
│ │ 2. ConnectionStateBase : TypeOptionBase<int, ConnectionStateBase>, │ │
│ │ IConnectionState │ │
│ │ 3. [TypeCollection] ConnectionStates : │ │
│ │ TypeCollectionBase<ConnectionStateBase, │ │
│ │ IConnectionState> │ │
│ │ 4. [TypeOption] OpenConnectionState : ConnectionStateBase │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
▼ Source Generator Processes
┌─────────────────────────────────────────────────────────────────────────┐
│ Generated Code (partial class ConnectionStates) │
│ - Static properties: Open, Closed, Opening, etc. │
│ - Static methods: ById(int), ByName(string), All() │
│ - FrozenDictionary backing stores (.NET 8+) │
│ - ImmutableDictionary backing stores (netstandard2.0) │
└─────────────────────────────────────────────────────────────────────────┘
TypeOptionBase<TKey, T> - Why It's Required
TypeOptionBase<TKey, T> provides essential functionality that the source generator depends on.
From TypeOptionBase.cs:12-88:
public abstract class TypeOptionBase<TKey, T> : ITypeOption<TKey, T>
where TKey : IEquatable<TKey>
where T : ITypeOption<TKey, T>
{
/// <summary>
/// Gets the unique identifier for this type option value.
/// </summary>
[TypeLookup("ById")]
public virtual TKey Id { get; }
/// <summary>
/// Gets the name of this type option value.
/// </summary>
[TypeLookup("ByName")]
public string Name { get; }
/// <summary>
/// Gets the category of this type option value.
/// </summary>
public string Category => string.IsNullOrEmpty(_category) ? "NotCategorized" : _category;
/// <summary>
/// Gets the configuration key for this type option value.
/// Used for configuration lookups and service registration.
/// </summary>
public string ConfigurationKey { get; }
/// <summary>
/// Gets the display name for this type option value.
/// Used for user-facing displays and documentation.
/// </summary>
public string DisplayName { get; }
/// <summary>
/// Gets the description of this type option value.
/// Provides detailed information about what this option does.
/// </summary>
public string Description { get; }
protected TypeOptionBase(TKey id, string name) : this(id, name, string.Empty)
{
}
protected TypeOptionBase(TKey id, string name, string? category)
{
if (name == null) throw new ArgumentNullException(nameof(name));
Id = id;
Name = name;
_category = category ?? string.Empty;
ConfigurationKey = $"TypeOptions:{name}";
DisplayName = name;
Description = $"Type option: {name}";
}
}
What the Source Generator Does:
- Scans for
[TypeOption]attributes - Reads
IdandNamefrom TypeOptionBase properties (via[TypeLookup]attributes) - Generates
FrozenDictionary<TKey, T>for ID lookups (.NET 8+) orImmutableDictionary<TKey, T>(netstandard2.0) - Generates
FrozenDictionary<string, T>for name lookups - Creates static properties using the TypeOption name
Without TypeOptionBase: Generator cannot read Id/Name at compile time, causing build failures.
Project Structure and Source Generator References
Abstractions Project (Where TypeCollection Lives)
<ItemGroup>
<PackageReference Include="FractalDataWorks.Collections" Version="*" />
<PackageReference Include="FractalDataWorks.Collections.SourceGenerators" Version="*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
Concrete Project (Where TypeOptions Are Implemented)
<ItemGroup>
<ProjectReference Include="..\Project.Abstractions\Project.Abstractions.csproj" />
<ProjectReference Include="..\FractalDataWorks.Collections.SourceGenerators\FractalDataWorks.Collections.SourceGenerators.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
PrivateAssets="none" />
<None Include="..\FractalDataWorks.Collections.SourceGenerators\bin\$(Configuration)\netstandard2.0\FractalDataWorks.Collections.SourceGenerators.dll"
Pack="true"
PackagePath="analyzers/dotnet/cs"
Visible="false"
Condition="Exists('..\FractalDataWorks.Collections.SourceGenerators\bin\$(Configuration)\netstandard2.0\FractalDataWorks.Collections.SourceGenerators.dll')" />
</ItemGroup>
Critical Settings Explained:
OutputItemType="Analyzer"- Makes project reference act as analyzerReferenceOutputAssembly="false"- Don't reference DLL at compile timePrivateAssets="none"- CRITICAL: Propagates generator to consuming projects<None Include=...>- Embeds generator DLL so consumers can access generated code
Consumer Projects
<ItemGroup>
<ProjectReference Include="..\Project\Project.csproj" />
</ItemGroup>
Common Architecture Mistakes
WRONG: Missing TypeOptionBase
// THIS WILL NOT WORK
public abstract class FilterOperatorBase // Missing: TypeOptionBase inheritance
{
public int Id { get; set; }
public string Name { get; set; }
}
Problem: Source generator cannot read Id/Name at compile time.
WRONG: Missing ITypeOption Interface
// THIS WILL NOT WORK
public interface IFilterOperator // Missing: ITypeOption<TKey, TBase> extension
{
}
Problem: Type constraints fail, collection cannot be properly typed.
WRONG: Base Class Not Implementing Interface
// THIS WILL NOT WORK
public abstract class FilterOperatorBase : TypeOptionBase<int, FilterOperatorBase>
// Missing: , IFilterOperator
{
}
Problem: Generic constraints broken, compilation fails.
WRONG: Wrong TypeCollection Parameters
// THIS WILL NOT WORK
[TypeCollection(typeof(FilterOperatorBase), typeof(FilterOperatorBase), typeof(FilterOperators))]
// Wrong: Second parameter should be IFilterOperator interface
public abstract partial class FilterOperators : TypeCollectionBase<FilterOperatorBase, FilterOperatorBase>
{
}
Problem: Loses polymorphism benefits, breaks interface abstraction.
CORRECT: Complete 4-Component Pattern
See the Connection States example above for the correct pattern from actual source files. The pattern requires:
- Interface extends
ITypeOption<TKey, TBase>(e.g.,IConnectionState : ITypeOption<int, ConnectionStateBase>) - Base class inherits
TypeOptionBase<TKey, T>AND implements interface - TypeCollection with correct parameters:
(typeof(Base), typeof(Interface), typeof(Collection)) - TypeOptions marked with
[TypeOption]and inherit from base class
Generated API
All collections automatically generate the following. From the generated ConnectionStates.TypeCollection.g.cs:
Static Properties (One Per TypeOption)
// Returns concrete type, not interface
public static ClosedConnectionState Closed { get; }
public static OpeningConnectionState Opening { get; }
public static OpenConnectionState Open { get; }
public static ExecutingConnectionState Executing { get; }
// ... one for each TypeOption
Lookup Methods (From TypeOptionBase Properties with [TypeLookup] attributes)
// Primary key lookup (uses Id property with [TypeLookup("ById")])
// Returns Empty if not found
public static IConnectionState ById(int value);
// Name lookup (uses Name property with [TypeLookup("ByName")])
// Returns Empty if not found
public static IConnectionState ByName(string value);
Collection Methods
// Returns all registered TypeOptions
public static IReadOnlyCollection<IConnectionState> All();
// Empty sentinel instance for failed lookups (property, not method)
public static IConnectionState Empty { get; }
Performance Characteristics
- Dictionary Lookups: Uses
FrozenDictionaryfor ID/name lookups on .NET 8+,ImmutableDictionaryon netstandard2.0 - Compile-time Discovery: All types validated and discovered at compile time
- Thread Safety: All generated collections are immutable and thread-safe
- Cross-Assembly Discovery: Finds TypeOptions across all referenced assemblies
Validation Rules
- TypeOptionBase Required: Base classes MUST inherit from
TypeOptionBase<TKey, T> - ITypeOption Required: Interfaces MUST extend
ITypeOption<TKey, TBase> - Interface Implementation: Base classes MUST implement the interface
- TypeOption Attribute Required: Concrete types MUST have
[TypeOption(typeof(Collection), "Name")] - Unique IDs: Each TypeOption must have a unique ID within its collection
- Unique Names: Each TypeOption must have a unique name within its collection
- Generic Consistency:
TGenericmust match interface type in TypeCollection attribute
Error Codes
- TC001: Type inherits from collection base but missing
[TypeOption]attribute - TC002: TGeneric in base class doesn't match defaultReturnType in attribute
- TC003: TBase in base class doesn't match baseType in attribute
- TC004: Duplicate option names in collection
- TC005: Collection not found for TypeOption attribute
- TC006: Base class doesn't inherit from
TypeOptionBase<TKey, T> - TC007: Interface doesn't extend
ITypeOption<TKey, TBase>
Best Practices
- Follow the 4-Component Pattern: Interface + Base + Collection + TypeOptions
- Abstractions Placement: Place collections in abstractions for maximum discoverability
- TypeOptionBase Inheritance: Always inherit from
TypeOptionBase<TKey, T> - Descriptive Names: Use clear, meaningful names in
[TypeOption]attributes - Unique IDs: Assign unique IDs within the collection
- Primary Constructors: Use C# 12 primary constructors for concise TypeOption syntax
- Proper Generator References: Use
PrivateAssets="none"and embed the generator DLL
Cross-Project Extensibility
Any project can add new TypeOptions by inheriting from the base class and marking with [TypeOption]. The source generator will discover TypeOptions across all referenced assemblies.
Example pattern (not actual source - for illustration):
// In MyCustom.Extensions project
using FractalDataWorks.Collections.Attributes;
using FractalDataWorks.Services.Connections.Abstractions;
[TypeOption(typeof(ConnectionStates), "CustomState")]
public sealed class CustomConnectionState() : ConnectionStateBase(100, "CustomState");
After building, the custom state is available via ConnectionStates.ByName("CustomState").
This enables plugin architectures where core defines contracts (collections + base types + interfaces) and implementations can be provided by any assembly.
Deferred Freeze Pattern (Cross-Assembly Registration)
TypeCollections use a deferred freeze pattern to support cross-assembly registration via NuGet packages. This ensures TypeOptions defined in separate packages are registered before the collection is accessed.
The Problem
sequenceDiagram
participant App as Application
participant Col as ConnectionStates
participant Lib as Extensions Package
Note over App: Application starts
App->>Col: ConnectionStates.All()
Note over Col: Collection freezes!
Col-->>App: Returns built-in states only
Note over Lib: Custom states never registered
Static constructors only run when something in that assembly is accessed. If you call ConnectionStates.All() before loading custom extensions, those options aren't included.
The Solution
Collections stay mutable until first access, then freeze into a FrozenDictionary:
flowchart TB
subgraph BeforeAccess["Before First Access"]
A[Module initializers run] --> B[RegisterMember adds to pending list]
B --> C[Static constructors run]
C --> D[More RegisterMember calls]
end
subgraph FirstAccess["On First Access"]
E[Code calls All/ById/ByName] --> F[EnsureFrozen called]
F --> G[_frozen = true]
G --> H[Build FrozenDictionary]
H --> I[Future RegisterMember throws]
end
BeforeAccess --> FirstAccess
Generated Registration Infrastructure
public partial class ConnectionStates
{
// Pending registrations (mutable before freeze)
private static readonly List<IConnectionState> _pendingRegistrations = new();
private static readonly object _lock = new();
private static volatile bool _frozen;
private static FrozenDictionary<int, IConnectionState>? _all;
// Static constructor registers compile-time discovered options
static ConnectionStates()
{
RegisterMember(new OpenConnectionState());
RegisterMember(new ClosedConnectionState());
// ... other built-in states
}
// Called by module initializers for cross-assembly registration
public static void RegisterMember(IConnectionState state)
{
if (_frozen)
throw new InvalidOperationException("Collection is frozen");
lock (_lock)
{
if (!_pendingRegistrations.Any(p => p.Id == state.Id))
_pendingRegistrations.Add(state);
}
}
// Called on first access
private static void EnsureFrozen()
{
if (_all != null) return;
lock (_lock)
{
_frozen = true;
_all = _pendingRegistrations.ToFrozenDictionary(x => x.Id);
}
}
public static FrozenDictionary<int, IConnectionState> All()
{
EnsureFrozen();
return _all!;
}
}
Module Initializers for NuGet Packages
For TypeOptions in separate NuGet packages, the Collections.SourceGenerators.Registration package generates module initializers in consuming assemblies:
// Generated in the consuming application
internal static class TypeOptionModuleInitializer
{
[ModuleInitializer]
internal static void RegisterTypeOptions()
{
// Register options from referenced packages
ConnectionStates.RegisterMember(new CustomConnectionState());
}
}
This runs before Main(), ensuring all options are registered before the collection is accessed.
For Package Authors
To enable transitive registration, embed the Registration generator in your package:
<ItemGroup>
<None Include="$(OutputPath)FractalDataWorks.Collections.SourceGenerators.Registration.dll"
Pack="true"
PackagePath="analyzers/dotnet/cs" />
</ItemGroup>
See the Registration Generator README for complete details.
Advanced: Parent-Child Collections (TypeOption)
TypeCollections can be nested to create hierarchical collection structures using the TypeOption and TypeOptionName properties on the [TypeCollection] attribute.
Example: Roslyn Commands as Child of Development Commands
From RoslynCommands.cs:1-15:
using FractalDataWorks.Collections.Attributes;
using FractalDataWorks.Commands.Development.Abstractions;
namespace FractalDataWorks.Roslyn.Commands.Abstractions;
/// <summary>
/// Type collection for Roslyn commands.
/// Child collection of <see cref="DevelopmentCommands"/> for C# specific commands.
/// Discovers all commands marked with [TypeOption(typeof(RoslynCommands), "CommandName")].
/// </summary>
[TypeCollection(typeof(RoslynCommandBase), typeof(IRoslynCommand), typeof(RoslynCommands),
TypeOption = typeof(DevelopmentCommands), TypeOptionName = "Roslyn")]
public static partial class RoslynCommands
{
}
How Parent-Child Works
- Parent Collection (
DevelopmentCommands): Collects child collections as TypeOptions - Child Collection (
RoslynCommands): HasTypeOptionandTypeOptionNameset to register with parent - The generator creates registration code so
DevelopmentCommands.ByName("Roslyn")returns the RoslynCommands collection
Reference Architecture: ConnectionStates
For the definitive reference implementation, see the files in FractalDataWorks.Services.Connections.Abstractions:
- Interface:
IConnectionState.cs - Base Class:
ConnectionStateBase.cs - Collection:
ConnectionStates.cs - TypeOptions:
OpenConnectionState.cs,ClosedConnectionState.cs,ExecutingConnectionState.cs, etc.
This implementation demonstrates the complete, correct pattern.
| 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
-
net10.0
NuGet packages (22)
Showing the top 5 NuGet packages that depend on FractalDataWorks.Collections:
| Package | Downloads |
|---|---|
|
FractalDataWorks.Abstractions
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
|
|
FractalDataWorks.Configuration
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
|
|
FractalDataWorks.Commands.Abstractions
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
|
|
FractalDataWorks.Commands.Data.Abstractions
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
|
|
FractalDataWorks.Commands.Data
Development tools and utilities for the FractalDataWorks ecosystem. Build: |
GitHub repositories
This package is not used by any popular GitHub repositories.