kdyf.Common 1.0.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package kdyf.Common --version 1.0.0
                    
NuGet\Install-Package kdyf.Common -Version 1.0.0
                    
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="kdyf.Common" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="kdyf.Common" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="kdyf.Common" />
                    
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 kdyf.Common --version 1.0.0
                    
#r "nuget: kdyf.Common, 1.0.0"
                    
#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 kdyf.Common@1.0.0
                    
#: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=kdyf.Common&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=kdyf.Common&version=1.0.0
                    
Install as a Cake Tool

kdyf.Common

NuGet License: MIT

Common utilities and base classes for KDYF projects. Provides reusable components for dependency injection testing, invocation tracking, and collection extensions.

Features

  • KdyfTestBase: Abstract base class for MSTest unit tests with built-in dependency injection
  • InvocationTracker: Thread-safe tracker for preventing duplicate service registrations
  • Collection Extensions: Utility methods for IEnumerable operations
  • Service Collection Extensions: Helper methods for service registration tracking

Installation

dotnet add package kdyf.Common

Components

KdyfTestBase

Abstract base class for unit tests that require dependency injection with MSTest framework.

Features
  • Automatic service provider setup and teardown
  • Configuration management with appsettings.json support
  • Built-in lifecycle hooks (OnSetup, OnCleanup)
  • Helper methods for service resolution
Usage
using kdyf.Common.Test.Base;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

[TestClass]
public class MyServiceTests : KdyfTestBase
{
    protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // Register your services
        services.AddTransient<IMyService, MyService>();
        services.AddSingleton<IMyRepository, MyRepository>();
    }

    [TestMethod]
    public void MyService_ShouldDoSomething()
    {
        // Arrange
        var myService = GetService<IMyService>();

        // Act
        var result = myService.DoSomething();

        // Assert
        Assert.IsNotNull(result);
    }
}
Advanced Usage
[TestClass]
public class AdvancedTests : KdyfTestBase
{
    private ILogger<AdvancedTests>? _logger;

    protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddLogging();
        services.AddTransient<IMyService, MyService>();
    }

    protected override void OnSetup()
    {
        // Called after ServiceProvider is built
        _logger = GetService<ILogger<AdvancedTests>>();
        _logger.LogInformation("Test starting");
    }

    protected override void OnCleanup()
    {
        // Called before ServiceProvider is disposed
        _logger?.LogInformation("Test completed");
    }

    [TestMethod]
    public void Test_WithScoping()
    {
        // Create a scope for scoped services
        using var scope = CreateScope();
        var scopedService = scope.ServiceProvider.GetRequiredService<IMyScopedService>();

        // Use the scoped service
        scopedService.DoWork();
    }

    [TestMethod]
    public void Test_WithOptionalService()
    {
        // Get service that might not be registered
        var optionalService = GetServiceOrNull<IOptionalService>();

        if (optionalService != null)
        {
            optionalService.DoOptionalWork();
        }
    }
}
Configuration Support

The base class automatically loads configuration from:

  1. appsettings.json (optional)
  2. appsettings.Test.json (optional)
  3. Environment variables
protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
    // Access configuration values
    var connectionString = configuration.GetConnectionString("DefaultConnection");
    var apiKey = configuration["ApiKey"];

    services.AddDbContext<MyDbContext>(options =>
        options.UseSqlServer(connectionString));
}
Custom Configuration

Override BuildConfiguration to customize configuration sources:

protected override IConfiguration BuildConfiguration()
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: true)
        .AddJsonFile("appsettings.Development.json", optional: true)
        .AddUserSecrets<MyServiceTests>()
        .AddEnvironmentVariables();

    return builder.Build();
}

InvocationTracker

Thread-safe tracker for recording method invocations to prevent duplicate operations.

Purpose

Prevents duplicate service registrations or repeated operations during dependency injection setup.

Usage with AlreadyInvoked
using kdyf.Common.Integration;
using Microsoft.Extensions.DependencyInjection;

public static class MyServiceExtensions
{
    public static IServiceCollection AddMyFeature(this IServiceCollection services)
    {
        // Prevent duplicate registration
        if (services.AlreadyInvoked(nameof(AddMyFeature)))
        {
            return services; // Already registered, skip
        }

        // Register services
        services.AddSingleton<IMyService, MyService>();
        services.AddTransient<IMyRepository, MyRepository>();

        return services;
    }
}
Example: Preventing Double Registration
var services = new ServiceCollection();

// First call - registers services
services.AddMyFeature();

// Second call - skips registration (already invoked)
services.AddMyFeature();

var serviceProvider = services.BuildServiceProvider();

// Only one instance of IMyService is registered
var myServices = serviceProvider.GetServices<IMyService>();
Assert.AreEqual(1, myServices.Count());
How It Works
  1. AlreadyInvoked creates a singleton InvocationTracker in the service collection (if not exists)
  2. Checks if the identifier has been recorded
  3. If not recorded, adds it to the tracker and returns false (not invoked before)
  4. If already recorded, returns true (already invoked)

The tracker is thread-safe and uses ConcurrentDictionary internally.

Collection Extensions

Utility extension methods for IEnumerable<T> collections.

IsNullOrEmpty

Determines whether an enumerable is null or contains no elements.

using System.Linq;

// Check if collection is null or empty
var items = GetItems(); // Could be null or empty
if (items.IsNullOrEmpty())
{
    Console.WriteLine("No items found");
    return;
}

// Process items
foreach (var item in items)
{
    Console.WriteLine(item);
}
Example: Guard Clauses
public void ProcessItems(IEnumerable<string>? items)
{
    if (items.IsNullOrEmpty())
    {
        throw new ArgumentException("Items cannot be null or empty", nameof(items));
    }

    // Safe to process
    foreach (var item in items)
    {
        Process(item);
    }
}
Example: Conditional Logic
public class OrderService
{
    public OrderSummary GetOrderSummary(Order order)
    {
        return new OrderSummary
        {
            OrderId = order.Id,
            HasItems = !order.Items.IsNullOrEmpty(),
            ItemCount = order.Items?.Count() ?? 0,
            Total = order.Items.IsNullOrEmpty()
                ? 0
                : order.Items.Sum(i => i.Price)
        };
    }
}

Note: IsNullOrEmpty() uses .Any() internally, which will materialize lazy enumerables. If you need to preserve lazy evaluation, consider using null checks and .Any() separately.

Best Practices

1. Use KdyfTestBase for Consistent Testing

Standardize your test infrastructure across all test projects:

// All test classes inherit from KdyfTestBase
[TestClass]
public class MyServiceTests : KdyfTestBase
{
    protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // Consistent service registration pattern
        services.AddMyApplicationServices(configuration);
    }
}

2. Prevent Duplicate Registrations

Use AlreadyInvoked in extension methods that might be called multiple times:

public static IServiceCollection AddMyInfrastructure(this IServiceCollection services)
{
    if (services.AlreadyInvoked(nameof(AddMyInfrastructure)))
        return services;

    // Register once
    services.AddHttpClient();
    services.AddMemoryCache();

    return services;
}

3. Leverage Configuration in Tests

Use configuration files for test data and connection strings:

// appsettings.Test.json
{
  "ConnectionStrings": {
    "TestDatabase": "Server=(localdb)\\mssqllocaldb;Database=TestDb;Trusted_Connection=True"
  },
  "TestSettings": {
    "TimeoutSeconds": 30,
    "MockExternalApis": true
  }
}
protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
    var testSettings = configuration.GetSection("TestSettings");
    services.Configure<TestSettings>(testSettings);
}

4. Use Null-Safe Collection Checks

Replace verbose null and empty checks with IsNullOrEmpty():

// ❌ Verbose
if (items == null || !items.Any())
{
    return;
}

// ✅ Concise
if (items.IsNullOrEmpty())
{
    return;
}

5. Clean Up Resources Properly

Override OnCleanup for proper resource disposal:

protected override void OnCleanup()
{
    // Clean up test data
    _testDatabase?.Dispose();
    _tempFiles?.ForEach(File.Delete);
}

Thread Safety

  • ✅ InvocationTracker: Thread-safe using ConcurrentDictionary
  • ✅ AlreadyInvoked: Thread-safe, can be called concurrently
  • ⚠️ KdyfTestBase: Not thread-safe, each test should have its own instance (handled by MSTest)

Requirements

  • .NET 8.0 or higher
  • Microsoft.Extensions.DependencyInjection.Abstractions 8.0.2+
  • MSTest framework (for KdyfTestBase)
  • kdyf.Operations: Operations orchestration framework
  • kdyf.Notifications: Reactive notification system
  • kdyf.Notifications.Redis: Redis transport for notifications

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues, questions, or contributions, please visit the GitHub repository.


Made with ❤️ by Kreadyf SRL

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 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 was computed.  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 (1)

Showing the top 1 NuGet packages that depend on kdyf.Common:

Package Downloads
kdyf.Notifications

Reactive notification system for .NET with multi-transport support. Provides a composable notification infrastructure with InMemory (System.Reactive) and Redis transports. Features include: fluent builder API, composite pattern for multiple transports, automatic deduplication across transports, tag-based filtering, type-safe notification routing, health checks, and seamless integration with .NET dependency injection. Supports both fire-and-forget and reactive observable patterns.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated