Skip to content

Use Cases for the ConnectSoft Library Template

The ConnectSoft.LibraryTemplate is designed to streamline the development of reusable .NET libraries. Its flexibility and pre-configured features make it suitable for a variety of scenarios, from creating utility libraries to crafting core components for enterprise applications.

Use Cases

Utility Libraries

  • Description:
    • Create libraries that provide common utility functions for strings, numbers, dates, and more.
  • Example:
    • Develop a library with reusable extensions for data validation or string manipulation.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.Extensions.Utils
    
  2. Add Utility Methods:
    public static class StringExtensions
    {
        public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(value);
    }
    
  3. Distribute as a NuGet Package:
    • Use the pre-configured pipeline to publish the library for internal or external use.

Core Framework Components

  • Description:
    • Build foundational libraries for shared use across microservices or enterprise applications.
  • Example:
    • Create a library for common domain entities, value objects, or aggregate roots.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.Domain.Core
    
  2. Define Domain Entities:
    public class User
    {
        public Guid Id { get; private set; }
        public string Name { get; private set; }
        public User(Guid id, string name)
        {
            Id = id;
            Name = name;
        }
    }
    

API Client Libraries

  • Description:
    • Create libraries for interacting with external APIs, abstracting complexities from application layers.
  • Example:
    • Build a client library for integrating with Azure Cognitive Services.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.Azure.CognitiveServices
    
  2. Add API Integration:
    public class TranslatorClient
    {
        private readonly HttpClient _httpClient;
    
        public TranslatorClient(HttpClient httpClient) => _httpClient = httpClient;
    
        public async Task<string> TranslateAsync(string text, string targetLanguage)
        {
            var response = await _httpClient.GetAsync($"translate?text={text}&to={targetLanguage}");
            return await response.Content.ReadAsStringAsync();
        }
    }
    

Localization Libraries

  • Description:
    • Build libraries to manage localization and translation resources for global applications.
  • Example:
    • Develop a localization library with pre-configured Resx or JSON support.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.Localization
    
  2. Add Localization Resources:
    • Include Resx files for multiple languages:
      Resources/
        Messages.en.resx
        Messages.fr.resx
      

Testing Frameworks

  • Description:
    • Create libraries for unit, integration, or performance testing utilities.
  • Example:
    • Develop a testing library that includes custom assertions or mocks.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.Testing.Utils
    
  2. Add Testing Utilities:
    public static class AssertExtensions
    {
        public static void IsNullOrEmpty(string value)
        {
            if (!string.IsNullOrEmpty(value))
                throw new Exception("Value is not null or empty.");
        }
    }
    

Multi-Tenant Components

  • Description:
    • Create libraries for managing multi-tenancy in SaaS applications.
  • Example:
    • Develop a library for tenant isolation and tenant-specific configuration.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.MultiTenancy
    
  2. Add Multi-Tenant Logic:
    public class TenantContext
    {
        public string TenantId { get; set; }
    }
    

Libraries with Cross-Cutting Concerns

  • Description:

    • Create libraries that integrate with DI containers, expose configurable settings, or require logging capabilities.
  • Example:

    • Develop a library for interacting with an external service that uses options for configuration and structured logging.

Implementation Example

  1. Generate the Library:
    dotnet new connectsoft-library --name ConnectSoft.ExternalServiceClient --useDI --useLogging --useOptions
    
  2. Configure Options

    public class ExternalServiceOptions
    {
        public const string SectionName = "ExternalService";
        public required string ApiKey { get; set; }
    }
    
  3. Add DI Setup

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddExternalService(this IServiceCollection services, IConfiguration config)
        {
            services.Configure<ExternalServiceOptions>(config.GetSection(ExternalServiceOptions.SectionName));
            services.AddOptions<ExternalServiceOptions>().ValidateDataAnnotations().ValidateOnStart();
            services.AddSingleton<ExternalServiceClient>();
            return services;
        }
    }
    
  4. Use Logging

    public class ExternalServiceClient
    {
        private readonly ILogger<ExternalServiceClient> _logger;
        public ExternalServiceClient(ILogger<ExternalServiceClient> logger) => _logger = logger;
    
        public void CallService() => _logger.LogInformation("Calling external service...");
    }
    
  5. Configure appsettings.json

    {
      "ExternalService": {
        "ApiKey": "your-api-key"
      }
    }
    

Real-World Examples

Reusable Extensions Library

  • Scenario:
    • A development team needs utility methods for string manipulation and date handling across projects.
  • Solution:
    • Use the Library Template to create ConnectSoft.Extensions.

Domain Model Library

  • Scenario:
    • A SaaS application needs a shared library of core domain entities.
  • Solution:
    • Generate ConnectSoft.Domain.Core and define domain models.

API Integration Library

  • Scenario:
    • A microservice requires integration with an external payment gateway.
  • Solution:
    • Create ConnectSoft.PaymentGateway with client classes for the gateway's API.

Testing Utilities Library

  • Scenario:
    • A QA team needs custom assertions and mocks for testing microservices.
  • Solution:
    • Build ConnectSoft.Testing.Utils to centralize testing utilities.

Multi-Framework Compatible Libraries

  • Scenario:
    • A developer wants to publish a library that can be used by both .NET 8 (LTS) applications and those already migrated to .NET 9.
  • Solution:

    • Use the template as-is with multi-targeting (net8.0;net9.0) already pre-configured in the .csproj.
    • Add runtime-specific logic using compiler directives if needed:

    #if NET9_0
        Console.WriteLine("Running on .NET 9");
    #else
        Console.WriteLine("Running on .NET 8");
    #endif
    
    - Benefits: - One NuGet package, full compatibility.

Benefits

  1. Accelerated Development:
    • Pre-configured settings eliminate setup time, allowing teams to focus on business logic.
  2. Consistency:
    • Ensures libraries adhere to ConnectSoft’s standards for quality and reusability.
  3. Scalability:
    • Enables seamless integration with CI/CD pipelines and artifact repositories.
  4. Cross-Cutting Concerns:
    • Supports optional DI, logging, and configuration for libraries with complex requirements.

Parameter-Specific Use Cases

Minimal Library (No Optional Features)

Scenario: Create a simple utility library without cross-cutting concerns.

Template Command:

dotnet new connectsoft-library --name ConnectSoft.Extensions.StringUtils \
  --useDI false --useLogging false --useOptions false --useMetrics false

Use Case: String manipulation utilities that don't need configuration or logging.

Example Implementation:

namespace ConnectSoft.Extensions.StringUtils
{
    public static class StringExtensions
    {
        public static string ToTitleCase(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return value;

            return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower());
        }

        public static bool IsValidEmail(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return false;

            try
            {
                var addr = new System.Net.Mail.MailAddress(value);
                return addr.Address == value;
            }
            catch
            {
                return false;
            }
        }
    }
}

Configuration-Only Library

Scenario: Library that provides configuration options and service registration.

Template Command:

dotnet new connectsoft-library --name ConnectSoft.Extensions.Configuration \
  --useDI --useLogging --useOptions --useMetrics false --useTracing false

Use Case: Configuration library that binds settings and registers services.

Example Implementation:

namespace ConnectSoft.Extensions.Configuration
{
    public class DatabaseOptions
    {
        public const string SectionName = "Database";

        [Required]
        public required string ConnectionString { get; set; }

        [Range(1, 300)]
        public int CommandTimeout { get; set; } = 30;

        public bool EnableRetryOnFailure { get; set; } = true;
    }

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddDatabase(
            this IServiceCollection services,
            IConfiguration configuration)
        {
            services.Configure<DatabaseOptions>(
                configuration.GetSection(DatabaseOptions.SectionName));

            services.AddOptions<DatabaseOptions>()
                .Bind(configuration.GetSection(DatabaseOptions.SectionName))
                .ValidateDataAnnotations()
                .ValidateOnStart();

            services.AddSingleton<IDatabaseService, DatabaseService>();

            return services;
        }
    }
}

Observability Library

Scenario: Library focused on monitoring, metrics, and tracing.

Template Command:

dotnet new connectsoft-library --name ConnectSoft.Extensions.Observability \
  --useDI --useLogging --useOptions false --useMetrics --useTracing

Use Case: Library that provides observability features for applications.

Example Implementation:

namespace ConnectSoft.Extensions.Observability
{
    public class ObservabilityMetrics
    {
        private readonly Counter<long> _operationCounter;
        private readonly Histogram<double> _operationDuration;

        public ObservabilityMetrics(IMeterFactory meterFactory)
        {
            var meter = meterFactory.Create("ConnectSoft.Observability");
            _operationCounter = meter.CreateCounter<long>("observability.operations.count");
            _operationDuration = meter.CreateHistogram<double>("observability.operations.duration", "ms");
        }

        public void RecordOperation(string operationName, double durationMs)
        {
            _operationCounter.Add(1, 
                new KeyValuePair<string, object?>("operation", operationName));
            _operationDuration.Record(durationMs,
                new KeyValuePair<string, object?>("operation", operationName));
        }
    }

    public static class ObservabilityDiagnostics
    {
        public const string ActivitySourceName = "ConnectSoft.Observability";
        public static readonly ActivitySource ActivitySource = new(ActivitySourceName);

        public static Activity? StartOperation(string operationName, string? itemId = null)
        {
            var tags = new List<KeyValuePair<string, object?>>
            {
                new("operation", operationName)
            };

            if (!string.IsNullOrEmpty(itemId))
            {
                tags.Add(new KeyValuePair<string, object?>("item.id", itemId));
            }

            return ActivitySource.StartActivity(operationName, ActivityKind.Internal, tags: tags);
        }
    }
}

Scenario: Library with all features enabled for comprehensive functionality.

Template Command:

dotnet new connectsoft-library --name ConnectSoft.Integration.ExternalService \
  --useDI --useLogging --useOptions --useMetrics --useTracing

Use Case: Integration library that needs configuration, logging, metrics, and tracing.

Example Implementation:

namespace ConnectSoft.Integration.ExternalService
{
    public class ExternalServiceOptions
    {
        public const string SectionName = "ExternalService";

        [Required]
        [Url]
        public required string BaseUrl { get; set; }

        [Required]
        public required string ApiKey { get; set; }

        [Range(1, 300)]
        public int TimeoutSeconds { get; set; } = 30;
    }

    public class ExternalServiceMetrics
    {
        private readonly Counter<long> _requestCounter;
        private readonly Histogram<double> _requestDuration;
        private readonly Counter<long> _errorCounter;

        public ExternalServiceMetrics(IMeterFactory meterFactory)
        {
            var meter = meterFactory.Create("ConnectSoft.ExternalService");
            _requestCounter = meter.CreateCounter<long>("externalservice.requests.count");
            _requestDuration = meter.CreateHistogram<double>("externalservice.requests.duration", "ms");
            _errorCounter = meter.CreateCounter<long>("externalservice.errors.count");
        }

        public void RecordRequest(double durationMs, string status)
        {
            _requestCounter.Add(1, new KeyValuePair<string, object?>("status", status));
            _requestDuration.Record(durationMs, new KeyValuePair<string, object?>("status", status));
        }

        public void RecordError(string errorType)
        {
            _errorCounter.Add(1, new KeyValuePair<string, object?>("error.type", errorType));
        }
    }

    public class ExternalServiceClient
    {
        private readonly ExternalServiceOptions _options;
        private readonly ILogger<ExternalServiceClient> _logger;
        private readonly ExternalServiceMetrics _metrics;
        private readonly HttpClient _httpClient;

        public ExternalServiceClient(
            IOptions<ExternalServiceOptions> options,
            ILogger<ExternalServiceClient> logger,
            ExternalServiceMetrics metrics,
            HttpClient httpClient)
        {
            _options = options.Value;
            _logger = logger;
            _metrics = metrics;
            _httpClient = httpClient;
        }

        public async Task<string> CallApiAsync(string endpoint)
        {
            var sw = Stopwatch.StartNew();

            using var scope = ExternalServiceDiagnostics.StartActivityScope(
                _logger,
                "ExternalService.CallApi",
                new[] { new KeyValuePair<string, object?>("endpoint", endpoint) });

            try
            {
                _logger.LogInformation("Calling external service endpoint {Endpoint}", endpoint);

                var response = await _httpClient.GetAsync($"{_options.BaseUrl}/{endpoint}");
                response.EnsureSuccessStatusCode();

                var result = await response.Content.ReadAsStringAsync();

                sw.Stop();
                _metrics.RecordRequest(sw.ElapsedMilliseconds, "success");

                _logger.LogInformation("External service call completed in {Duration}ms", sw.ElapsedMilliseconds);

                return result;
            }
            catch (Exception ex)
            {
                sw.Stop();
                _metrics.RecordError(ex.GetType().Name);
                _logger.LogError(ex, "Error calling external service endpoint {Endpoint}", endpoint);
                throw;
            }
        }
    }

    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddExternalService(
            this IServiceCollection services,
            IConfiguration configuration)
        {
            services.Configure<ExternalServiceOptions>(
                configuration.GetSection(ExternalServiceOptions.SectionName));

            services.AddOptions<ExternalServiceOptions>()
                .Bind(configuration.GetSection(ExternalServiceOptions.SectionName))
                .ValidateDataAnnotations()
                .ValidateOnStart();

            services.AddSingleton<ExternalServiceMetrics>();
            services.AddHttpClient<ExternalServiceClient>();
            services.AddScoped<ExternalServiceClient>();

            return services;
        }
    }
}

Integration Patterns

ASP.NET Core Integration

Scenario: Library that integrates with ASP.NET Core applications.

Implementation:

// In Startup.cs or Program.cs
services.AddMyLibrary(configuration);

// Use in controllers
public class MyController : ControllerBase
{
    private readonly IMyService _service;

    public MyController(IMyService service)
    {
        _service = service;
    }

    [HttpGet]
    public IActionResult Get()
    {
        _service.DoWork();
        return Ok();
    }
}

Microservice Integration

Scenario: Library used across multiple microservices.

Benefits:

  • Consistent patterns across services
  • Shared observability
  • Unified configuration
  • Standardized error handling

Console Application Integration

Scenario: Library used in console applications.

Implementation:

var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

services.AddMyLibrary(configuration);

var serviceProvider = services.BuildServiceProvider();
var myService = serviceProvider.GetRequiredService<IMyService>();
myService.DoWork();

Best Practices by Use Case

Utility Libraries

  1. Keep it Simple: Don't add unnecessary dependencies
  2. Pure Functions: Prefer stateless, pure functions
  3. Extension Methods: Use extension methods for discoverability
  4. No Configuration: Avoid configuration for simple utilities

Integration Libraries

  1. Configuration First: Use Options pattern for all settings
  2. Resilience: Implement retry policies and circuit breakers
  3. Observability: Include metrics and tracing
  4. Error Handling: Provide clear error messages and exceptions

Domain Libraries

  1. Clean Architecture: Separate domain logic from infrastructure
  2. Value Objects: Use value objects for domain concepts
  3. Immutable Types: Prefer immutable types where possible
  4. Domain Events: Consider domain events for complex scenarios

Infrastructure Libraries

  1. Abstractions: Provide abstractions, not implementations
  2. Extension Methods: Use extension methods for registration
  3. Configuration: Support configuration via Options pattern
  4. Observability: Include metrics and logging

Conclusion

The ConnectSoft Library Template provides a powerful foundation for creating reusable, high-quality libraries in .NET Core. From utility libraries to multi-tenant components, it supports a wide range of use cases, ensuring faster development and robust integration with modern development workflows.

By choosing the right combination of template parameters, you can create libraries that are:

  • Minimal: Simple utilities without unnecessary dependencies
  • Configurable: Libraries with rich configuration options
  • Observable: Libraries with comprehensive monitoring
  • Full-Featured: Libraries with all capabilities enabled

Each use case benefits from the template's built-in best practices, testing support, and CI/CD integration.