Momentum.Extensions.XmlDocs
0.0.1
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
<PackageReference Include="Momentum.Extensions.XmlDocs" Version="0.0.1" />
<PackageVersion Include="Momentum.Extensions.XmlDocs" Version="0.0.1" />
<PackageReference Include="Momentum.Extensions.XmlDocs" />
paket add Momentum.Extensions.XmlDocs --version 0.0.1
#r "nuget: Momentum.Extensions.XmlDocs, 0.0.1"
#:package Momentum.Extensions.XmlDocs@0.0.1
#addin nuget:?package=Momentum.Extensions.XmlDocs&version=0.0.1
#tool nuget:?package=Momentum.Extensions.XmlDocs&version=0.0.1
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 | Versions 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. |
-
net9.0
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.8)
- Microsoft.SourceLink.GitHub (>= 8.0.0)
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 |