Skip to content

Features of the ConnectSoft Library Template

The ConnectSoft.LibraryTemplate is designed to streamline the creation and maintenance of high-quality .NET Core libraries. It incorporates best practices, modern tooling, and pre-configured settings to simplify development and ensure maintainability.

Key Features

Structured Solution

  • Primary Library Project:
    • A pre-configured project ready for developing reusable components.
  • Unit Test Project:
    • Includes an MSTest-based test project for validating library functionality.
  • Templated Documentation:
    • A README.md file is pre-generated, providing a foundation for library documentation.

CI/CD Integration

  • Automated Pipelines:
    • YAML templates for building, testing, and publishing NuGet packages.
  • Code Coverage:
    • Integrated tools to calculate and enforce test coverage standards.
  • Artifact Management:
    • Automatically publishes NuGet packages to a shared artifact repository for reuse in the ConnectSoft ecosystem.
  • Multi-TFM Build Support:
    • Azure Pipelines installs and builds both .NET 8 and .NET 9 SDKs, ensuring full compatibility before publishing the NuGet package.

Best Practices Implementation

  • Coding Guidelines:
    • Adheres to Microsoft’s .NET library design and coding standards.
  • NuGet Metadata:
    • Includes NuSpec templates for proper NuGet package metadata, ensuring compatibility and discoverability.

Multi-Targeting

Supported Frameworks: .NET 8 (LTS) and .NET 9

The template generates libraries that target both .NET 8 and .NET 9 simultaneously, allowing a single NuGet package to support both framework versions.

Implementation:

<PropertyGroup>
  <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
</PropertyGroup>

Benefits: - Single NuGet package for multiple framework versions - Maximum compatibility with consuming applications - Framework-specific code using compiler directives when needed

Framework-Specific Code:

#if NET9_0
    // .NET 9 specific code
    var result = new Feature().UseNewApi();
#else
    // .NET 8 fallback
    var result = new Feature().UseLegacyApi();
#endif

CI/CD Support: - Azure Pipelines installs both .NET 8 and .NET 9 SDKs - Builds and tests against both frameworks - Ensures compatibility before publishing

Static Code Analyzers

The template includes a comprehensive set of static code analyzers to ensure code quality, consistency, and security.

Included Analyzers:

Analyzer Purpose Version
StyleCop.Analyzers Enforces consistent C# style and naming conventions 1.1.118
SonarAnalyzer.CSharp Detects bugs, vulnerabilities, and code smells 10.15.0.120848
Meziantou.Analyzer Additional code quality best practices 2.0.215
AsyncFixer Fixes common async/await mistakes 1.6.0
Asyncify Ensures correct async method usage 0.9.7
Microsoft.VisualStudio.Threading.Analyzers Threading and async patterns enforcement 17.14.15

Configuration:

  • Analyzers are configured in Directory.Packages.props
  • Applied automatically to all projects
  • No manual setup required
  • Can be customized via .editorconfig or GlobalSuppressions.cs

Benefits:

  • Consistent code style across the library
  • Early detection of bugs and security issues
  • Improved code maintainability
  • Compliance with .NET coding guidelines

Central Package Management (CPM)

The template uses Central Package Management (CPM) to simplify and standardize NuGet package versioning.

Implementation:

  • Package versions defined in Directory.Packages.props
  • No versions in individual .csproj files
  • Single source of truth for package versions

Benefits:

  • Easier package upgrades (update one file)
  • Consistent dependencies across projects
  • Cleaner project files
  • Reduced version conflicts

Example:

<!-- Directory.Packages.props -->
<ItemGroup>
  <PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.10" />
</ItemGroup>

<!-- .csproj -->
<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Logging" />
  <!-- No Version attribute needed -->
</ItemGroup>

Learn More: Microsoft Docs: Central Package Management

Solution Format (.slnx)

The template generates both modern .slnx (XML-based) and legacy .sln (text-based) solution files.

Modern Format (.slnx):

  • Performance: 48% faster CLI builds compared to legacy format
  • Requirements: Visual Studio 2022 v17.14+ or .NET SDK 9.0.200+
  • Primary Format: Used by default for all development

Legacy Format (.sln):

  • Compatibility: Works with older tooling
  • Fallback: Used when .slnx is not supported
  • Generated: Always generated alongside .slnx

Benefits:

  • Improved build performance
  • Better IDE integration
  • Modern tooling support
  • Backward compatibility maintained

CI/CD Integration

The template includes pre-configured Azure DevOps pipelines for automated build, test, and publish workflows.

Pipeline Features:

  • Multi-Targeting: Builds and tests against .NET 8 and .NET 9
  • Code Coverage: Collects and reports code coverage (Cobertura format)
  • Build Quality Checks: Enforces minimum code coverage threshold (configurable)
  • NuGet Packaging: Creates NuGet packages automatically
  • Artifact Publishing: Publishes packages to Azure Artifacts (on master branch)
  • Package Validation: Checks for deprecated and vulnerable packages

Pipeline Steps:

  1. Install .NET SDK 8 and 9
  2. Authenticate with NuGet feeds
  3. Restore packages
  4. Check deprecated packages
  5. Check vulnerable packages
  6. Build solution (Release configuration)
  7. Run tests with code coverage
  8. Publish code coverage results
  9. Validate build quality (coverage threshold)
  10. Pack NuGet package
  11. Push to Azure Artifacts (master branch only)

Configurable Variables:

  • buildDefinitionNumber: Build definition ID (from template parameter)
  • codeCoverageThreshold: Minimum coverage percentage (default: 0, can be set to 70+)
  • useLocalSqlDb: Enable SQL LocalDB for integration tests

For detailed pipeline documentation, see the Runbook.

Optional Cross-Cutting Concerns

The template supports optional features that can be enabled or disabled during template instantiation. Each feature includes complete implementation examples and best practices.

Dependency Injection (UseDI)

Default: true (enabled)
CLI Flag: --useDI or --di

Enables Dependency Injection support using Microsoft.Extensions.DependencyInjection.

What Gets Generated:

  • Package references: Microsoft.Extensions.DependencyInjection.Abstractions, Microsoft.Extensions.DependencyInjection
  • Enables service registration extension methods
  • Supports IServiceCollection usage throughout the library

Usage Example:

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddMyLibrary(this IServiceCollection services)
    {
        services.AddSingleton<IMyService, MyService>();
        return services;
    }
}

Benefits:

  • Loose coupling between components
  • Improved testability with mock injection
  • Standard .NET DI patterns
  • Integration with ASP.NET Core and other frameworks

For detailed DI patterns, see the Architecture Guide.

Structured Logging (UseLogging)

Default: true (enabled)
CLI Flag: --useLogging or --logging

Enables structured logging using Microsoft.Extensions.Logging.

What Gets Generated:

  • Package references: Microsoft.Extensions.Logging.Abstractions, Microsoft.Extensions.Logging, Microsoft.Extensions.Logging.Debug, Microsoft.Extensions.Logging.Console
  • Enables ILogger<T> usage in library code
  • Supports structured logging patterns

Usage Example:

public class MyService
{
    private readonly ILogger<MyService> _logger;

    public MyService(ILogger<MyService> logger)
    {
        _logger = logger;
    }

    public void DoWork()
    {
        _logger.LogInformation("Processing item {ItemId} at {Timestamp}", itemId, DateTime.UtcNow);
    }
}

Benefits:

  • Structured logging with key-value pairs
  • Log level filtering
  • Multiple log providers (Console, Debug, File, etc.)
  • Integration with Application Insights, Serilog, etc.
  • Correlation with distributed tracing (when UseActivitySource=true)

Options Pattern (UseOptions)

Default: true (enabled)
CLI Flag: --useOptions or --options

Enables the Options pattern with configuration binding and validation.

What Gets Generated:

  • Package references: Microsoft.Extensions.Options, Microsoft.Extensions.Options.DataAnnotations
  • Options/ folder with sample options class
  • Source-generated options validator using OptionsValidatorAttribute
  • Configuration binding examples

Usage Example:

// Options class
public class MyLibraryOptions
{
    public const string SectionName = "MyLibrary";

    [Required]
    [MinLength(3)]
    public required string ApiKey { get; set; }

    [Range(1, 100)]
    public int MaxRetries { get; set; } = 3;
}

// Service registration
services.Configure<MyLibraryOptions>(configuration.GetSection(MyLibraryOptions.SectionName));
services.AddOptions<MyLibraryOptions>()
    .ValidateDataAnnotations()
    .ValidateOnStart();

Benefits:

  • Strongly-typed configuration
  • Validation on startup
  • Environment-specific configuration
  • Source-generated validators (performance)
  • Integration with appsettings.json, environment variables, etc.

For detailed configuration patterns, see the Configuration Guide.

Metrics Support (UseMetrics)

Default: true (enabled)
CLI Flag: --useMetrics or --metrics

Enables built-in metrics support for OpenTelemetry-compatible metrics.

What Gets Generated:

  • Package references: Microsoft.Extensions.Diagnostics
  • Metrics/ folder with sample metrics class
  • IMeterFactory integration
  • Example counter and histogram metrics

Usage Example:

public class MyLibraryMetrics
{
    private readonly Counter<long> requestCounter;
    private readonly Histogram<double> requestDuration;

    public MyLibraryMetrics(IMeterFactory meterFactory)
    {
        var meter = meterFactory.Create("MyLibrary");
        requestCounter = meter.CreateCounter<long>("mylibrary.requests.count");
        requestDuration = meter.CreateHistogram<double>("mylibrary.requests.duration", "ms");
    }

    public void RecordRequest(double durationMs)
    {
        requestCounter.Add(1);
        requestDuration.Record(durationMs);
    }
}

Benefits:

  • OpenTelemetry-compatible metrics
  • Standard metric types (Counter, Histogram, Gauge)
  • Integration with Prometheus, Application Insights, etc.
  • Performance monitoring
  • Custom business metrics

For detailed metrics patterns, see the Metrics & Observability Guide.

ActivitySource Tracing (UseActivitySource)

Default: false (disabled)
CLI Flag: --useTracing or --traces

Enables ActivitySource support for distributed tracing with OpenTelemetry integration.

What Gets Generated:

  • Diagnostics/ folder with ActivitySource implementation
  • Samples/ folder with tracing demo
  • Log correlation with trace IDs
  • OpenTelemetry-compatible tracing

Usage Example:

using var activity = LibraryTemplateDiagnostics.StartActivity("MyOperation");
activity?.SetTag("operation.type", "process");
activity?.SetTag("item.id", itemId);

// Your code here

// Activity automatically ends when disposed

Benefits:

  • Distributed tracing across services
  • OpenTelemetry integration
  • Log correlation with trace IDs
  • Performance profiling
  • Request flow visualization

For detailed tracing patterns, see the Metrics & Observability Guide.

Multi-Environment Support

  • CLI Support:
    • Use the .NET CLI to quickly scaffold a new library.
  • Visual Studio Integration:
    • Create libraries directly from Visual Studio with an intuitive workflow.

Preconfigured Settings

  • Git Integration:
    • Includes .gitignore tailored for .NET projects.
  • Code Analysis:
    • Pre-configured rules to enforce coding standards and maintain code quality.

Flexible Parameters

  • Customizable Build Definition:
    • Pass a custom build definition number to tailor the CI/CD pipeline.
  • Output Options:
    • Specify output directories and configurations using CLI parameters.

CLI Features

Help Output

The template supports extensive CLI commands for easy project creation:

ConnectSoft Library Template (C#)
Author: Dmitry Khaymov
Description: A solution and projects for creating and publishing a library project.

Usage:
  dotnet new connectsoft-library [options] [template options]

Options:
  -n, --name <name>       The name for the output being created. If no name is specified, the name of the output
                          directory is used.
  -o, --output <output>   Location to place the generated output.
  --dry-run               Displays a summary of what would happen if the given command line were run.
  --force                 Forces content to be generated even if it would change existing files.
  --project <project>     The project that should be used for context evaluation.
  -lang, --language <C#>  Specifies the template language to instantiate.
  --type <solution>       Specifies the template type to instantiate.

Template options:
  -b, --buildDefinitionNumber <buildDefinitionNumber>  Overrides the build definition number.
                                                       Type: string
  --useDI               Include support for IServiceCollection-based registration
  --useLogging          Include support for Microsoft.Extensions.Logging
  --useOptions          Include support for options binding and validation

Examples

dotnet new connectsoft-library --name MyLibrary --buildDefinitionNumber 46
dotnet new connectsoft-library --name ConnectSoft.Extensions.MyFeature --output ./MyFeatureLib

Visual Studio Features

Intuitive Workflow

  • Search and select the ConnectSoft Library Template in the Create a new project dialog.
  • Configure project-specific parameters such as name and location.

Solution Components

  • Library Project:
    • Ready for development with pre-configured settings.
  • Test Project:
    • MSTest framework integration for unit testing.
  • Documentation:
    • Auto-generated README.md for library details.

Integration with ConnectSoft Framework

  • Reusable NuGet Packages:
    • Artifacts are automatically compatible with other projects in the ConnectSoft ecosystem.
  • Consistent CI/CD Workflows:
    • Ensures uniformity in build, test, and deployment processes across libraries.

Real-World Benefits

Time Savings

  • Pre-configured settings eliminate setup overhead.

Quality Assurance

  • Integrated testing and code analysis ensure high-quality libraries.

Scalability

  • CI/CD pipelines enable seamless growth and automation.

Feature Combinations

Full-Featured Library (All features enabled):

dotnet new connectsoft-library --name MyLibrary \
  --useDI --useLogging --useOptions --useMetrics --useTracing
Best for: Libraries that need comprehensive observability and configuration.

Minimal Library (No optional features):

dotnet new connectsoft-library --name MyLibrary \
  --useDI false --useLogging false --useOptions false --useMetrics false
Best for: Simple utility libraries without cross-cutting concerns.

Configuration Library (DI + Logging + Options):

dotnet new connectsoft-library --name MyLibrary \
  --useDI --useLogging --useOptions --useMetrics false --useTracing false
Best for: Libraries that provide configuration and service registration.

Observability Library (Logging + Metrics + Tracing):

dotnet new connectsoft-library --name MyLibrary \
  --useDI --useLogging --useOptions false --useMetrics --useTracing
Best for: Libraries focused on monitoring and observability.

Feature Dependencies

While features can be enabled independently, some work better together:

  • UseOptions + UseDI: Options pattern benefits from DI for service registration
  • UseActivitySource + UseLogging: Tracing integrates with logging for correlation
  • UseMetrics + UseLogging: Metrics and logs provide complementary observability

Next Steps

References