Momentum.Extensions.XmlDocs 0.0.1

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Momentum.Extensions.XmlDocs --version 0.0.1
                    
NuGet\Install-Package Momentum.Extensions.XmlDocs -Version 0.0.1
                    
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="Momentum.Extensions.XmlDocs" Version="0.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Momentum.Extensions.XmlDocs" Version="0.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Momentum.Extensions.XmlDocs" />
                    
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 Momentum.Extensions.XmlDocs --version 0.0.1
                    
#r "nuget: Momentum.Extensions.XmlDocs, 0.0.1"
                    
#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 Momentum.Extensions.XmlDocs@0.0.1
                    
#: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=Momentum.Extensions.XmlDocs&version=0.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Momentum.Extensions.XmlDocs&version=0.0.1
                    
Install as a Cake Tool

Momentum.Extensions.XmlDocs

A powerful .NET library for parsing, processing, and accessing XML documentation files generated by the C# compiler. This library provides comprehensive access to XML documentation comments including summaries, parameters, return values, examples, and response codes - essential for building documentation tools, OpenAPI generators, and code analysis utilities.

Installation

Install the package via NuGet Package Manager:

dotnet add package Momentum.Extensions.XmlDocs

Or add to your project file:

<PackageReference Include="Momentum.Extensions.XmlDocs" Version="1.0.0" />

Key Features

  • Asynchronous XML Documentation Loading: Efficiently loads and parses XML documentation files with async/await patterns
  • Comprehensive Member Documentation: Access documentation for types, methods, properties, constructors, and parameters
  • OpenAPI Integration: Built-in support for enriching OpenAPI specifications with XML documentation
  • Performance Optimized: Thread-safe caching with ConcurrentDictionary for fast repeated access
  • Generic Type Support: Handles complex generic type signatures and parameter documentation
  • Constructor Parameter Mapping: Maps constructor parameters to property documentation for records and classes
  • Structured Documentation Model: Rich data model supporting summaries, remarks, examples, parameters, and response codes
  • Error Resilient: Graceful handling of missing files, malformed XML, and incomplete documentation

Basic Usage

Loading XML Documentation

using Microsoft.Extensions.Logging;
using Momentum.Extensions.XmlDocs;

// Create the service (typically registered in DI container)
var logger = LoggerFactory.Create(b => b.AddConsole()).CreateLogger<XmlDocumentationService>();
var xmlService = new XmlDocumentationService(logger);

// Load documentation from XML file
var xmlPath = Path.Combine(AppContext.BaseDirectory, "MyAssembly.xml");
bool loaded = await xmlService.LoadDocumentationAsync(xmlPath);

if (loaded)
{
    Console.WriteLine("XML documentation loaded successfully");
}
else
{
    Console.WriteLine("Failed to load XML documentation");
}

Accessing Type Documentation

// Get documentation for a specific type
var typeDoc = xmlService.GetTypeDocumentation(typeof(MyClass));

if (typeDoc != null)
{
    Console.WriteLine($"Summary: {typeDoc.Summary}");
    Console.WriteLine($"Remarks: {typeDoc.Remarks}");
    Console.WriteLine($"Example: {typeDoc.Example}");
}

Method Documentation

// Get method documentation using reflection
var methodInfo = typeof(MyService).GetMethod("ProcessOrder");
var methodDoc = xmlService.GetMethodDocumentation(methodInfo);

if (methodDoc != null)
{
    Console.WriteLine($"Method: {methodDoc.Summary}");
    Console.WriteLine($"Returns: {methodDoc.Returns}");
    
    // Access parameter documentation
    foreach (var param in methodDoc.Parameters)
    {
        Console.WriteLine($"Parameter {param.Key}: {param.Value.Description}");
        if (!string.IsNullOrEmpty(param.Value.Example))
        {
            Console.WriteLine($"  Example: {param.Value.Example}");
        }
    }
    
    // Access response documentation
    foreach (var response in methodDoc.Responses)
    {
        Console.WriteLine($"Response {response.Key}: {response.Value}");
    }
}

Property Documentation

var propertyInfo = typeof(OrderModel).GetProperty("OrderId");
var propertyDoc = xmlService.GetPropertyDocumentation(propertyInfo);

if (propertyDoc != null)
{
    Console.WriteLine($"Property: {propertyDoc.Summary}");
}

Advanced Usage

Dependency Injection Registration

using Microsoft.Extensions.DependencyInjection;
using Momentum.Extensions.XmlDocs;

// Register in DI container as singleton for performance
services.AddSingleton<IXmlDocumentationService, XmlDocumentationService>();

// Use in your services
public class DocumentationGenerator
{
    private readonly IXmlDocumentationService _xmlDocs;
    
    public DocumentationGenerator(IXmlDocumentationService xmlDocs)
    {
        _xmlDocs = xmlDocs;
    }
    
    public async Task GenerateDocsAsync(string assemblyPath)
    {
        var xmlPath = Path.ChangeExtension(assemblyPath, ".xml");
        await _xmlDocs.LoadDocumentationAsync(xmlPath);
        
        // Use the loaded documentation...
    }
}

Loading Multiple Documentation Files

// Load documentation from multiple assemblies
var xmlFiles = new[]
{
    "MyCore.xml",
    "MyApi.xml",
    "MyModels.xml"
};

var loadTasks = xmlFiles.Select(xmlService.LoadDocumentationAsync);
var results = await Task.WhenAll(loadTasks);

bool anyLoaded = results.Any(r => r);
Console.WriteLine($"Loaded {results.Count(r => r)} of {xmlFiles.Length} documentation files");

Processing Event Documentation (Records/Classes)

// Useful for documentation generators that work with records
public class EventDocumentationProcessor
{
    private readonly IXmlDocumentationService _xmlService;
    
    public EventDocumentationProcessor(IXmlDocumentationService xmlService)
    {
        _xmlService = xmlService;
    }
    
    public EventDocumentation ProcessEvent(Type eventType)
    {
        var typeDoc = _xmlService.GetTypeDocumentation(eventType);
        var properties = GetPropertyDocumentation(eventType);
        
        return new EventDocumentation
        {
            TypeName = eventType.Name,
            Summary = typeDoc?.Summary ?? "No documentation available",
            Remarks = typeDoc?.Remarks,
            Example = typeDoc?.Example,
            Properties = properties
        };
    }
    
    private Dictionary<string, string> GetPropertyDocumentation(Type type)
    {
        var docs = new Dictionary<string, string>();
        
        foreach (var property in type.GetProperties())
        {
            var propDoc = _xmlService.GetPropertyDocumentation(property);
            docs[property.Name] = propDoc?.Summary ?? "No description available";
        }
        
        return docs;
    }
}

Advanced Member Name Resolution

// Accessing documentation by XML member name directly
public class AdvancedDocumentationAccess
{
    private readonly IXmlDocumentationService _xmlService;
    
    public AdvancedDocumentationAccess(IXmlDocumentationService xmlService)
    {
        _xmlService = xmlService;
    }
    
    public void AccessDocumentationDirectly()
    {
        // Access type documentation directly
        var typeDoc = _xmlService.GetDocumentation("T:MyNamespace.MyClass");
        
        // Access method documentation directly
        var methodDoc = _xmlService.GetDocumentation("M:MyNamespace.MyClass.ProcessOrder(System.String,System.Int32)");
        
        // Access property documentation directly  
        var propertyDoc = _xmlService.GetDocumentation("P:MyNamespace.MyClass.OrderId");
        
        // Access constructor documentation
        var constructorDoc = _xmlService.GetDocumentation("M:MyNamespace.MyClass.#ctor(System.String)");
    }
}

API Reference

IXmlDocumentationService Interface

Core service interface for XML documentation operations:

public interface IXmlDocumentationService
{
    Task<bool> LoadDocumentationAsync(string xmlFilePath);
    XmlDocumentationInfo? GetDocumentation(string memberName);
    XmlDocumentationInfo? GetTypeDocumentation(Type type);
    XmlDocumentationInfo? GetMethodDocumentation(MethodInfo methodInfo);
    XmlDocumentationInfo? GetPropertyDocumentation(PropertyInfo propertyInfo);
    void ClearCache();
}

XmlDocumentationInfo Class

Rich documentation model containing all parsed information:

public class XmlDocumentationInfo
{
    public string? Summary { get; set; }           // <summary> content
    public string? Remarks { get; set; }           // <remarks> content  
    public string? Returns { get; set; }           // <returns> content
    public string? Example { get; set; }           // <example> content
    
    // Parameter documentation with optional examples
    public Dictionary<string, ParameterInfo> Parameters { get; }
    
    // Response documentation keyed by status code
    public Dictionary<string, string?> Responses { get; }
    
    public record ParameterInfo(string? Description, string? Example);
}

Key Methods

Method Description Performance Notes
LoadDocumentationAsync Loads XML file asynchronously One-time operation, cached results
GetTypeDocumentation Gets documentation for a Type O(1) lookup after loading
GetMethodDocumentation Gets documentation for MethodInfo O(1) lookup, handles generic types
GetPropertyDocumentation Gets documentation for PropertyInfo O(1) lookup
ClearCache Clears all cached documentation Use when memory optimization needed

Integration Scenarios

OpenAPI Documentation Enhancement

The library integrates seamlessly with ASP.NET Core OpenAPI:

// In Program.cs or Startup.cs
using Momentum.ServiceDefaults.Api.OpenApi.Extensions;

builder.Services.AddOpenApiWithXmlDocSupport(options =>
{
    // Additional OpenAPI configuration
    options.DocumentTitle = "My API";
    options.DocumentVersion = "v1";
});

// The service will automatically enrich OpenAPI specs with XML documentation

Source Generator Integration

// Example usage in source generators
[Generator]
public class DocumentationGenerator : ISourceGenerator
{
    public void Execute(GeneratorExecutionContext context)
    {
        var xmlService = new XmlDocumentationService(NullLogger<XmlDocumentationService>.Instance);
        
        // Load XML documentation for the current compilation
        var xmlPath = GetXmlDocumentationPath(context);
        var loaded = xmlService.LoadDocumentationAsync(xmlPath).GetAwaiter().GetResult();
        
        if (loaded)
        {
            // Generate code based on XML documentation
            GenerateCodeFromDocumentation(context, xmlService);
        }
    }
}

Documentation Tools and Analyzers

// Building custom documentation tools
public class DocumentationAnalyzer
{
    private readonly IXmlDocumentationService _xmlService;
    
    public DocumentationAnalyzer(IXmlDocumentationService xmlService)
    {
        _xmlService = xmlService;
    }
    
    public async Task<DocumentationReport> AnalyzeAssemblyAsync(string assemblyPath)
    {
        var xmlPath = Path.ChangeExtension(assemblyPath, ".xml");
        await _xmlService.LoadDocumentationAsync(xmlPath);
        
        var assembly = Assembly.LoadFrom(assemblyPath);
        var report = new DocumentationReport();
        
        foreach (var type in assembly.GetExportedTypes())
        {
            var typeDoc = _xmlService.GetTypeDocumentation(type);
            report.AddTypeAnalysis(type, typeDoc);
            
            // Analyze methods
            foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                var methodDoc = _xmlService.GetMethodDocumentation(method);
                report.AddMethodAnalysis(method, methodDoc);
            }
        }
        
        return report;
    }
}

Common Patterns

Automatic XML File Discovery

public static class XmlDocumentationLoader
{
    public static async Task<bool> LoadFromAssemblyLocationAsync(
        this IXmlDocumentationService service, 
        Assembly assembly)
    {
        var assemblyLocation = assembly.Location;
        var xmlPath = Path.ChangeExtension(assemblyLocation, ".xml");
        
        return await service.LoadDocumentationAsync(xmlPath);
    }
    
    public static async Task<int> LoadFromDirectoryAsync(
        this IXmlDocumentationService service,
        string directory)
    {
        var xmlFiles = Directory.GetFiles(directory, "*.xml");
        var loadTasks = xmlFiles.Select(service.LoadDocumentationAsync);
        var results = await Task.WhenAll(loadTasks);
        
        return results.Count(r => r);
    }
}

Documentation Validation

public class DocumentationValidator
{
    private readonly IXmlDocumentationService _xmlService;
    
    public ValidationResult ValidateType(Type type)
    {
        var result = new ValidationResult();
        var typeDoc = _xmlService.GetTypeDocumentation(type);
        
        // Validate type documentation
        if (string.IsNullOrEmpty(typeDoc?.Summary))
        {
            result.AddWarning($"Type {type.Name} missing summary documentation");
        }
        
        // Validate public methods
        foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
        {
            var methodDoc = _xmlService.GetMethodDocumentation(method);
            
            if (string.IsNullOrEmpty(methodDoc?.Summary))
            {
                result.AddWarning($"Method {method.Name} missing summary documentation");
            }
            
            // Validate parameter documentation
            foreach (var param in method.GetParameters())
            {
                if (!methodDoc?.Parameters.ContainsKey(param.Name!) == true)
                {
                    result.AddWarning($"Parameter {param.Name} in {method.Name} missing documentation");
                }
            }
        }
        
        return result;
    }
}

Caching and Performance Optimization

public class OptimizedDocumentationService
{
    private readonly IXmlDocumentationService _xmlService;
    private readonly Dictionary<Assembly, bool> _loadedAssemblies = new();
    
    public OptimizedDocumentationService(IXmlDocumentationService xmlService)
    {
        _xmlService = xmlService;
    }
    
    public async Task EnsureDocumentationLoadedAsync(Assembly assembly)
    {
        if (_loadedAssemblies.ContainsKey(assembly))
            return;
            
        var xmlPath = Path.ChangeExtension(assembly.Location, ".xml");
        var loaded = await _xmlService.LoadDocumentationAsync(xmlPath);
        _loadedAssemblies[assembly] = loaded;
    }
    
    public async Task<XmlDocumentationInfo?> GetTypeDocumentationAsync(Type type)
    {
        await EnsureDocumentationLoadedAsync(type.Assembly);
        return _xmlService.GetTypeDocumentation(type);
    }
}

Error Handling

The library provides robust error handling for common scenarios:

Missing XML Files

public async Task HandleMissingFilesAsync()
{
    var xmlService = new XmlDocumentationService(logger);
    
    // LoadDocumentationAsync returns false for missing files (no exceptions)
    bool loaded = await xmlService.LoadDocumentationAsync("NonExistent.xml");
    
    if (!loaded)
    {
        logger.LogWarning("XML documentation not found - API documentation may be incomplete");
        // Continue gracefully without documentation
    }
}

Malformed XML Handling

public async Task HandleMalformedXmlAsync()
{
    try
    {
        bool loaded = await xmlService.LoadDocumentationAsync("BadFile.xml");
        // Method returns false for malformed XML instead of throwing
        
        if (!loaded)
        {
            // Log warning and continue with default documentation
            logger.LogWarning("Failed to parse XML documentation file");
        }
    }
    catch (Exception ex)
    {
        // Unexpected errors are still caught and logged
        logger.LogError(ex, "Unexpected error loading XML documentation");
    }
}

Null Documentation Handling

public void HandleMissingDocumentation()
{
    var typeDoc = xmlService.GetTypeDocumentation(typeof(MyClass));
    
    // Always check for null - indicates no documentation found
    var summary = typeDoc?.Summary ?? "No documentation available";
    var remarks = typeDoc?.Remarks; // May be null even if typeDoc exists
    
    // Safe parameter access
    if (typeDoc?.Parameters.TryGetValue("parameterName", out var paramDoc) == true)
    {
        var description = paramDoc.Description ?? "No parameter description";
    }
}

Performance Considerations

When to Use

  • ✅ Documentation Tools: Perfect for generating API docs, markdown files, or OpenAPI specs
  • ✅ Development-Time Analysis: Ideal for build-time source generators and analyzers
  • ✅ Application Startup: Suitable for loading documentation during application initialization
  • ❌ Runtime Hot Paths: Avoid repeated loading in performance-critical application logic
  • ❌ Per-Request Operations: Don't load XML files on every HTTP request

Optimization Tips

// ✅ Good: Load once, use many times
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IXmlDocumentationService>(provider =>
    {
        var logger = provider.GetRequiredService<ILogger<XmlDocumentationService>>();
        var service = new XmlDocumentationService(logger);
        
        // Load documentation at startup
        var xmlPath = Path.Combine(AppContext.BaseDirectory, "MyApp.xml");
        service.LoadDocumentationAsync(xmlPath).GetAwaiter().GetResult();
        
        return service;
    });
}

// ✅ Good: Batch loading for multiple files
var xmlFiles = Directory.GetFiles(docsPath, "*.xml");
var loadTasks = xmlFiles.Select(xmlService.LoadDocumentationAsync);
await Task.WhenAll(loadTasks); // Load all files concurrently

// ❌ Avoid: Reloading the same file multiple times
foreach (var type in types)
{
    await xmlService.LoadDocumentationAsync(xmlPath); // Don't do this!
    var doc = xmlService.GetTypeDocumentation(type);
}

Memory Management

// Clear cache when memory optimization is needed
public class DocumentationService
{
    private readonly IXmlDocumentationService _xmlService;
    
    public async Task ProcessLargeDocumentationSetAsync(IEnumerable<string> xmlFiles)
    {
        try
        {
            foreach (var xmlFile in xmlFiles)
            {
                await _xmlService.LoadDocumentationAsync(xmlFile);
                ProcessDocumentation();
                
                // Clear cache periodically for large document sets
                _xmlService.ClearCache();
            }
        }
        finally
        {
            // Always clear cache when done
            _xmlService.ClearCache();
        }
    }
}

Examples and Best Practices

XML Documentation Format

Ensure your source code uses comprehensive XML documentation:

public async Task<OrderConfirmation> ProcessOrderAsync(string orderId, int priority)
{
    // Implementation
}

This comprehensive documentation makes Momentum.Extensions.XmlDocs a powerful, developer-friendly library for working with XML documentation in .NET applications. Whether you're building documentation generators, OpenAPI integrations, or code analysis tools, this library provides the foundation you need with excellent performance and error handling.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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 Momentum.Extensions.XmlDocs:

Package Downloads
Momentum.ServiceDefaults.Api

API-specific service defaults for Momentum platform extending the base ServiceDefaults with gRPC, OpenAPI documentation (Scalar), and API-focused configurations. Essential for Momentum API projects.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.2-preview.1 97 9/5/2025
0.0.1 188 8/29/2025
0.0.1-preview.1 104 9/4/2025
0.0.1-pre.18 103 9/3/2025
0.0.1-pre.17 111 9/2/2025
0.0.1-pre.16 163 8/29/2025
0.0.1-pre.15 157 8/28/2025
0.0.1-pre.14 325 8/21/2025
0.0.1-pre.13 127 8/21/2025
0.0.1-pre.12 128 8/20/2025
0.0.1-pre.11 128 8/18/2025
0.0.1-pre.10 114 8/18/2025
0.0.1-pre.9 110 8/18/2025
0.0.1-pre.8 115 8/18/2025
0.0.1-pre.7 112 8/18/2025
0.0.1-pre.6 119 8/18/2025
0.0.1-pre.5 115 8/18/2025
0.0.1-pre.3 171 8/27/2025