Thank you for your interest in contributing to Fox.ChainKit! This document provides guidelines and instructions for contributing to the project.
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
If you find a bug or have a feature request:
- Check if the issue already exists in the GitHub Issues
- If not, create a new issue with:
- Clear, descriptive title
- Detailed description of the problem or feature
- Steps to reproduce (for bugs)
- Expected vs actual behavior
- Code samples if applicable
- Environment details (.NET version, OS, etc.)
- Fork the repository and create a new branch from
main - Make your changes following the coding guidelines below
- Write or update tests for your changes
- Update documentation if needed (README, XML comments)
- Ensure all tests pass (
dotnet test) - Ensure build succeeds (
dotnet build) - Submit a pull request with:
- Clear description of changes
- Reference to related issues
- Summary of testing performed
Fox.ChainKit follows strict coding standards. Please review the Copilot Instructions for detailed guidelines.
- Language: All code, comments, and documentation must be in English
- Line Endings: CRLF
- Indentation: 4 spaces (no tabs)
- Namespaces: File-scoped (
namespace MyNamespace;) - Nullable: Enabled
- Language Version: latest
- Private Fields: camelCase without underscore prefix (e.g.,
value, not_value) - Public Members: PascalCase
- Local Variables: camelCase
- Use expression-bodied members for simple properties and methods
- Use auto-properties where possible
- Prefer
varonly when type is obvious - Maximum line length: 100 characters
- Add blank line after closing brace UNLESS next line is also
}
- XML Comments: Required for all public APIs
- Language: English
- Decorators: 98 characters width using
//======(no space after prefix) - File Headers: 3-line header (purpose + technical description + decorators)
Example:
//==================================================================================================
// Implements the chain execution engine.
// Executes handlers sequentially with diagnostics and exception handling support.
//==================================================================================================
namespace Fox.ChainKit;
//==================================================================================================
/// <summary>
/// Implements the chain of responsibility pattern for executing handlers sequentially.
/// </summary>
/// <typeparam name="TContext">The type of context object to process.</typeparam>
//==================================================================================================
public sealed class Chain<TContext> : IChain<TContext>
{
private readonly IServiceProvider serviceProvider;
//==============================================================================================
/// <summary>
/// Initializes a new instance of the <see cref="Chain{TContext}"/> class.
/// </summary>
/// <param name="serviceProvider">The service provider to resolve handlers.</param>
//==============================================================================================
public Chain(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
//==============================================================================================
/// <inheritdoc />
//==============================================================================================
public Task RunAsync(TContext context, CancellationToken cancellationToken = default)
{
// Implementation
}
}- Framework: xUnit
- Assertions: FluentAssertions
- Test Naming:
MethodName_should_expected_behavior - Coverage: Aim for 100% coverage of new code
- Test Structure:
- Arrange: Setup test data
- Act: Execute the method under test
- Assert: Verify expected behavior
Example:
[Fact]
public async Task RunAsync_should_execute_handlers_in_order()
{
// Arrange
var services = new ServiceCollection();
services.AddTransient<TestHandlerA>();
services.AddTransient<TestHandlerB>();
var serviceProvider = services.BuildServiceProvider();
var chain = new ChainBuilder<TestContext>(serviceProvider)
.AddHandler<TestHandlerA>()
.AddHandler<TestHandlerB>()
.Build();
var context = new TestContext();
// Act
await chain.RunAsync(context);
// Assert
context.ExecutedHandlers.Should().ContainInOrder(
nameof(TestHandlerA),
nameof(TestHandlerB));
}Fox.ChainKit follows Clean Architecture and SOLID principles:
- Single Responsibility: Each class has one clear purpose
- Open/Closed: Open for extension (via interfaces), closed for modification
- Liskov Substitution: All implementations are substitutable
- Interface Segregation: Small, focused interfaces
- Dependency Inversion: Depend on abstractions, not concretions
- No Reflection: All handler resolution through DI
- No Runtime Discovery: Handlers are explicitly registered
- No Magic: Behavior is explicit and predictable
- Explicit API: Clear method names and parameters
- DI-First: Designed for dependency injection from the ground up
Fox.ChainKit/
├── src/
│ ├── Fox.ChainKit/ # Core package
│ │ ├── *.cs # Public interfaces and types
│ │ ├── Internal/ # Internal implementation details
│ │ └── Extensions/ # Extension methods
│ └── Fox.ChainKit.ResultKit/ # ResultKit integration
│ ├── *.cs # Public interfaces
│ ├── Internal/ # Internal adapters
│ └── Extensions/ # Extension methods
├── tests/
│ ├── Fox.ChainKit.Tests/ # Core tests
│ └── Fox.ChainKit.ResultKit.Tests/ # ResultKit tests
└── samples/
└── Fox.ChainKit.Demo/ # Demo application
- Update tests: Ensure your changes are covered by tests
- Update documentation: Keep README and XML comments up to date
- Follow coding standards: Use provided
.editorconfigand copilot instructions - Keep commits clean:
- Use clear, descriptive commit messages
- Squash commits if needed before merging
- Update CHANGELOG.md: Add entry under
[Unreleased]section - Ensure CI passes: All tests must pass and build must succeed
Use clear, imperative commit messages:
Add support for async conditional handlers
- Implement AddConditionalHandlerAsync method
- Add unit tests for async conditions
- Update documentation
When proposing new features, please consider:
- Scope: Does this fit the focused nature of Fox.ChainKit?
- Complexity: Does this add unnecessary complexity?
- Dependencies: Does this require new external dependencies?
- Breaking Changes: Will this break existing code?
- Use Cases: What real-world scenarios does this address?
Fox.ChainKit aims to be lightweight and focused. Features should align with the core Chain of Responsibility pattern.
- .NET 8 SDK or later
- Visual Studio 2022+ or Rider (recommended)
- Git
- Clone the repository:
git clone https://github.com/akikari/Fox.ChainKit.git
cd Fox.ChainKit- Restore dependencies:
dotnet restore- Build the solution:
dotnet build- Run tests:
dotnet test- Run the sample application:
dotnet run --project samples/Fox.ChainKit.Demo/Fox.ChainKit.Demo.csprojIf you have questions about contributing, feel free to:
- Open a GitHub Discussion
- Create an issue labeled
question - Reach out to the maintainers
By contributing to Fox.ChainKit, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to Fox.ChainKit! 🎉