FractalDataWorks.Services
0.4.0-preview.6
dotnet add package FractalDataWorks.Services --version 0.4.0-preview.6
NuGet\Install-Package FractalDataWorks.Services -Version 0.4.0-preview.6
<PackageReference Include="FractalDataWorks.Services" Version="0.4.0-preview.6" />
<PackageVersion Include="FractalDataWorks.Services" Version="0.4.0-preview.6" />
<PackageReference Include="FractalDataWorks.Services" />
paket add FractalDataWorks.Services --version 0.4.0-preview.6
#r "nuget: FractalDataWorks.Services, 0.4.0-preview.6"
#:package FractalDataWorks.Services@0.4.0-preview.6
#addin nuget:?package=FractalDataWorks.Services&version=0.4.0-preview.6&prerelease
#tool nuget:?package=FractalDataWorks.Services&version=0.4.0-preview.6&prerelease
FractalDataWorks.Services
Service factory implementations for the FractalDataWorks framework. Provides base classes for service factories, provider registration, and DI container integration using Railway-Oriented Programming patterns.
Overview
This package contains concrete implementations of service infrastructure:
ServiceFactory<TService, TConfiguration>- Base factory with FastGenericNew instantiationGenericServiceFactory<TService, TConfiguration>- Default factory for most servicesServiceFactoryProvider- Thread-safe registry for service factoriesFactoryRegistration- Registration metadata with lifetime support- MessageLogging classes for structured logging
Target Framework
- net10.0
Installation
<PackageReference Include="FractalDataWorks.Services" Version="1.0.0" />
Key Components
ServiceFactory - Base Factory Implementation
From ServiceFactory.cs:21-77:
public abstract class ServiceFactory<TService, TConfiguration> : IServiceFactory<TService, TConfiguration> where TService : class
where TConfiguration : class, IGenericConfiguration
{
private readonly ILogger _logger;
protected ILogger Logger => _logger;
protected ServiceFactory(ILogger? logger)
{
_logger = logger ?? NullLogger.Instance;
}
public virtual IGenericResult<TService> Create(TConfiguration configuration)
{
var serviceTypeName = typeof(TService).Name;
if (configuration == null)
{
return GenericResult<TService>.Failure(ServiceLogger.InvalidConfigurationWarning(_logger, "Configuration cannot be null"));
}
ServiceLogger.ValidatingServiceConfiguration(_logger, serviceTypeName);
var serviceLogger = NullLogger<TService>.Instance;
if (FastNew.TryCreateInstance<TService, ILogger<TService>, TConfiguration>(serviceLogger, configuration, out var service))
{
ServiceLogger.FastGenericServiceCreated(_logger, serviceTypeName);
ServiceLogger.ServiceStarted(_logger, serviceTypeName);
return GenericResult<TService>.Success(service, $"Service created successfully: {serviceTypeName}");
}
ServiceLogger.FastGenericServiceCreationFailed(_logger, serviceTypeName);
var exception = new InvalidOperationException("FastNew failed to create service");
return GenericResult<TService>.Failure(ServiceFactoryLogger.CreateServiceError(_logger, exception, serviceTypeName));
}
}
GenericServiceFactory - Default Factory
From GenericServiceFactory.cs:22-71:
public class GenericServiceFactory<TService, TConfiguration> : ServiceFactory<TService, TConfiguration>
where TService : class, IGenericService
where TConfiguration : class, IGenericConfiguration
{
private readonly ILogger<GenericServiceFactory<TService, TConfiguration>> _logger;
public GenericServiceFactory(ILogger<GenericServiceFactory<TService, TConfiguration>> logger)
: base(logger)
{
_logger = logger;
}
public GenericServiceFactory()
: base(null)
{
_logger = NullLogger<GenericServiceFactory<TService, TConfiguration>>.Instance;
}
public override IGenericResult<TService> Create(TConfiguration configuration)
{
var serviceTypeName = typeof(TService).Name;
ServiceFactoryLogger.CreatingService(_logger, serviceTypeName, configuration.Name ?? "unnamed");
var serviceLogger = NullLogger<TService>.Instance;
if (FastNew.TryCreateInstance<TService, ILogger<TService>, TConfiguration>(serviceLogger, configuration, out var service))
{
ServiceFactoryLogger.ServiceCreatedWithFastNew(_logger, serviceTypeName);
return GenericResult<TService>.Success(service, ServiceLogger.ConfigurationCannotBeNull(_logger, serviceTypeName));
}
return GenericResult<TService>.Failure(ServiceFactoryLogger.ServiceCreationFailed(_logger, serviceTypeName, "No suitable constructor found"));
}
}
ServiceFactoryProvider - Factory Registry
From ServiceFactoryProvider.cs:18-92:
public sealed class ServiceFactoryProvider : IServiceFactoryProvider
{
private readonly Dictionary<string, FactoryRegistration> _registrations;
private readonly object _lock;
public ServiceFactoryProvider()
{
_registrations = new Dictionary<string, FactoryRegistration>(StringComparer.OrdinalIgnoreCase);
_lock = new object();
}
public IGenericResult RegisterFactory(string typeName, IServiceFactory factory)
{
return RegisterFactory(typeName, factory, ServiceLifetimes.Scoped);
}
public IGenericResult RegisterFactory(string typeName, IServiceFactory factory, IServiceLifetime lifetime)
{
if (string.IsNullOrWhiteSpace(typeName))
return GenericResult.Failure("Service type name cannot be null or empty");
if (factory == null)
return GenericResult.Failure("Factory cannot be null");
if (lifetime == null)
return GenericResult.Failure("Lifetime cannot be null");
lock (_lock)
{
if (_registrations.ContainsKey(typeName))
{
return GenericResult.Failure($"Factory for service type '{typeName}' is already registered");
}
_registrations[typeName] = new FactoryRegistration
{
Factory = factory,
Lifetime = lifetime,
TypeName = typeName
};
}
return GenericResult.Success();
}
public IGenericResult<IServiceFactory> GetFactory(string typeName)
{
if (string.IsNullOrWhiteSpace(typeName))
return GenericResult<IServiceFactory>.Failure("Service type name cannot be null or empty");
lock (_lock)
{
if (_registrations.TryGetValue(typeName, out var registration))
{
return GenericResult<IServiceFactory>.Success(registration.Factory);
}
}
var availableTypes = string.Join(", ", GetRegisteredTypeNames());
return GenericResult<IServiceFactory>.Failure(
$"No factory registered for service type '{typeName}'. Available types: {availableTypes}");
}
}
FactoryRegistration - Registration Metadata
From FactoryRegistration.cs:17-66:
public sealed class FactoryRegistration
{
public IServiceFactory Factory { get; set; } = null!;
public IServiceLifetime Lifetime { get; set; } = ServiceLifetimes.Scoped;
public string TypeName { get; set; } = string.Empty;
public int Priority { get; set; } = 50;
public IDictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>(StringComparer.Ordinal);
}
DI Registration Extensions
From Extensions/ServiceFactoryRegistrationExtensions.cs:31-68:
public static class ServiceFactoryRegistrationExtensions
{
public static IServiceCollection AddServiceFactoryProvider(this IServiceCollection services)
{
services.AddSingleton<IServiceFactoryProvider, ServiceFactoryProvider>();
return services;
}
public static IServiceCollection RegisterConnectionFactories(
this IServiceCollection services,
Action<IConnectionFactoryRegistrationBuilder> configure)
{
if (configure == null)
throw new ArgumentNullException(nameof(configure));
services.AddServiceFactoryProvider();
var builder = new ConnectionFactoryRegistrationBuilder(services);
configure(builder);
return services;
}
}
Logging Infrastructure
ServiceLogger - Service Operation Logging
From Logging/ServiceLogger.cs:10-75:
public static partial class ServiceLogger
{
[MessageLogging(EventId = 5001, Level = LogLevel.Warning, Message = "Configuration cannot be null for service type '{serviceTypeName}'")]
public static partial IGenericMessage ConfigurationCannotBeNull(ILogger logger, string serviceTypeName);
[MessageLogging(EventId = 5002, Level = LogLevel.Warning, Message = "{errorMessage}")]
public static partial IGenericMessage InvalidConfigurationWarning(ILogger logger, string errorMessage);
[MessageLogging(EventId = 5003, Level = LogLevel.Debug, Message = "Validating service configuration for '{serviceTypeName}'")]
public static partial IGenericMessage ValidatingServiceConfiguration(ILogger logger, string serviceTypeName);
[MessageLogging(EventId = 5004, Level = LogLevel.Information, Message = "Fast generic service created: '{serviceTypeName}'")]
public static partial IGenericMessage FastGenericServiceCreated(ILogger logger, string serviceTypeName);
[MessageLogging(EventId = 5005, Level = LogLevel.Information, Message = "Service started: '{serviceTypeName}'")]
public static partial IGenericMessage ServiceStarted(ILogger logger, string serviceTypeName);
[MessageLogging(EventId = 5006, Level = LogLevel.Error, Message = "Fast generic service creation failed for '{serviceTypeName}'")]
public static partial IGenericMessage FastGenericServiceCreationFailed(ILogger logger, string serviceTypeName);
[MessageLogging(EventId = 5007, Level = LogLevel.Error, Message = "Service type cast failed: cannot cast '{sourceType}' to '{targetType}'")]
public static partial IGenericMessage ServiceTypeCastFailed(ILogger logger, string sourceType, string targetType);
}
ServiceFactoryLogger - Factory Logging
From Logging/ServiceFactoryLogger.cs:12-118:
public static partial class ServiceFactoryLogger
{
[MessageLogging(
EventId = 7001,
Level = LogLevel.Debug,
Message = "Creating service '{serviceType}' with configuration '{configurationName}'")]
public static partial IGenericMessage CreatingService(
ILogger logger,
string serviceType,
string configurationName);
[MessageLogging(
EventId = 7003,
Level = LogLevel.Information,
Message = "Service '{serviceType}' created successfully using FastGenericNew")]
public static partial IGenericMessage ServiceCreatedWithFastNew(
ILogger logger,
string serviceType);
[MessageLogging(
EventId = 7004,
Level = LogLevel.Error,
Message = "Failed to create service '{serviceType}': {reason}")]
public static partial IGenericMessage ServiceCreationFailed(
ILogger logger,
string serviceType,
string reason);
[MessageLogging(
EventId = 7007,
Level = LogLevel.Error,
Message = "Failed to create service of type '{serviceType}'")]
public static partial IGenericMessage CreateServiceError(
ILogger logger,
Exception exception,
string serviceType);
}
Message Types
The package includes predefined message types for service operations:
ConfigurationCannotBeNullMessage- Configuration validationConfigurationNotInitializedMessage- Initialization errorsFastGenericCreationFailedMessage- FastGenericNew failuresServiceCreatedSuccessfullyMessage- Successful creationServiceCreationFailedMessage- Creation failuresRegistrationFailedMessage- DI registration errorsInvalidCommandTypeMessage- Command type mismatchesValidationFailedMessage- Validation errors
Dependencies
Project references from FractalDataWorks.Services.csproj:
FractalDataWorks.MessageLogging.Abstractions- MessageLogging infrastructureFractalDataWorks.MessageLogging.SourceGenerators- Source generator (analyzer)FractalDataWorks.Collections- TypeCollection supportFractalDataWorks.Configuration- Configuration base classesFractalDataWorks.Messages- Message infrastructureFractalDataWorks.Results- IGenericResult implementationFractalDataWorks.Services.Abstractions- ServiceType discoveryFractalDataWorks.Services.Abstractions- Service interfacesFractalDataWorks.Services.Connections.Abstractions- Connection abstractionsFractalDataWorks.Etl.Abstractions- ETL abstractions
Package references:
FastGenericNew.SourceGenerator- High-performance object creationFluentValidation- Configuration validationMicrosoft.Extensions.DependencyInjection.Abstractions- DI integrationMicrosoft.Extensions.Diagnostics.HealthChecks- Health check supportMicrosoft.Extensions.Hosting.Abstractions- Hosting integrationMicrosoft.Extensions.Logging.Abstractions- LoggingMicrosoft.Extensions.Options- Options pattern
Best Practices
- Use
ServiceFactory<TService, TConfiguration>as base for custom factories - Use
GenericServiceFactory<TService, TConfiguration>for standard service creation - Register factories with
AddServiceFactoryProvider()for centralized management - Use MessageLogging methods for structured logging with IGenericMessage return
- Return IGenericResult from all factory methods instead of throwing exceptions
- Use
ServiceLifetimes.Scoped,ServiceLifetimes.Singleton, orServiceLifetimes.Transientfor lifetime specification
Related Packages
- FractalDataWorks.Services.Abstractions - Service interfaces and base types
- FractalDataWorks.Configuration - Configuration base classes
- FractalDataWorks.Results - Railway-Oriented Programming
License
Copyright FractalDataWorks. All rights reserved.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- FluentValidation (>= 12.1.1)
- FractalDataWorks.Collections (>= 0.4.0-preview.6)
- FractalDataWorks.Configuration (>= 0.4.0-preview.6)
- FractalDataWorks.Etl.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.MessageLogging.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Messages (>= 0.4.0-preview.6)
- FractalDataWorks.Results (>= 0.4.0-preview.6)
- FractalDataWorks.Results.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Abstractions (>= 0.4.0-preview.6)
- FractalDataWorks.Services.Connections.Abstractions (>= 0.4.0-preview.6)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.1)
- Microsoft.Extensions.Options (>= 10.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|