Zooper.Octopus
1.0.0
dotnet add package Zooper.Octopus --version 1.0.0
NuGet\Install-Package Zooper.Octopus -Version 1.0.0
<PackageReference Include="Zooper.Octopus" Version="1.0.0" />
<PackageVersion Include="Zooper.Octopus" Version="1.0.0" />
<PackageReference Include="Zooper.Octopus" />
paket add Zooper.Octopus --version 1.0.0
#r "nuget: Zooper.Octopus, 1.0.0"
#:package Zooper.Octopus@1.0.0
#addin nuget:?package=Zooper.Octopus&version=1.0.0
#tool nuget:?package=Zooper.Octopus&version=1.0.0
Zooper.Octopus
<img src="icon.png" alt="Zooper.Octopus Logo" width="120" align="right"/>
Zooper.Octopus is a lightweight .NET library that simplifies the implementation of Hexagonal Architecture (Ports and Adapters) pattern in your applications. It provides a clean and intuitive way to define ports and automatically register their adapters in your dependency injection container.
Key Features
- Clean Architecture: Implements the Hexagonal Architecture pattern with clear separation of concerns
- Ports and Adapters: Provides a clear way to define ports and their implementations
- Dependency Injection: Automatic registration of adapters in your DI container
- Flexible Scanning: Multiple ways to scan and register adapters from different assemblies
- Minimal Dependencies: Only depends on Microsoft.Extensions.DependencyInjection and Scrutor
- Type-safe: Leverages C#'s type system for robust port definitions
- Testable: Designed with testability in mind from the ground up
Installation
dotnet add package Zooper.Octopus
Quick Start
Here's a basic example of implementing Hexagonal Architecture with Zooper.Octopus:
// Define your port (in your core/domain layer)
public interface IUserRepository : IPort
{
Task<User?> GetByIdAsync(Guid id);
Task SaveAsync(User user);
}
// Implement your adapter (in your infrastructure layer)
public class SqlUserRepository : IUserRepository
{
private readonly DbContext _dbContext;
public SqlUserRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<User?> GetByIdAsync(Guid id)
{
return await _dbContext.Users.FindAsync(id);
}
public async Task SaveAsync(User user)
{
_dbContext.Users.Update(user);
await _dbContext.SaveChangesAsync();
}
}
// Register adapters in your composition root
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Register all adapters from the current assembly
services.RegisterAdapters();
// Or register adapters from specific assemblies
services.RegisterAdapters(typeof(SqlUserRepository).Assembly);
// Or register adapters from multiple assemblies
services.RegisterAdapters(
typeof(SqlUserRepository).Assembly,
typeof(AnotherAdapter).Assembly
);
}
}
Core Concepts
Ports
Ports are interfaces that define the boundaries of your application. They represent the contracts that your application core expects to be fulfilled:
public interface IEmailService : IPort
{
Task SendEmailAsync(string to, string subject, string body);
}
Adapters
Adapters are the implementations of ports. They live in the infrastructure layer and provide the actual functionality:
public class SmtpEmailService : IEmailService
{
private readonly SmtpClient _smtpClient;
public SmtpEmailService(SmtpClient smtpClient)
{
_smtpClient = smtpClient;
}
public async Task SendEmailAsync(string to, string subject, string body)
{
var message = new MailMessage("noreply@example.com", to, subject, body);
await _smtpClient.SendMailAsync(message);
}
}
Registration
Zooper.Octopus provides several ways to register your adapters:
// Register all adapters from application dependencies
services.RegisterAdapters();
// Register adapters from a specific assembly
services.RegisterAdapters(typeof(SqlUserRepository).Assembly);
// Register adapters from multiple assemblies
services.RegisterAdapters(
typeof(SqlUserRepository).Assembly,
typeof(SmtpEmailService).Assembly
);
// Register adapters from the assembly containing a specific type
services.RegisterAdapters<SqlUserRepository>();
Best Practices
Port Organization
- Keep Ports Focused: Each port should have a single responsibility
- Use Meaningful Names: Port names should clearly indicate their purpose
- Define Clear Contracts: Port interfaces should be well-defined and stable
Adapter Implementation
- Keep Adapters Simple: Adapters should focus on implementing the port contract
- Handle Dependencies: Use constructor injection for dependencies
- Implement Error Handling: Adapters should handle errors appropriately
Testing
- Test Ports Independently: Test ports without their adapters
- Mock Adapters: Use mocks for testing the application core
- Test Adapters in Isolation: Test adapters with their specific dependencies
Examples
Check out the Zooper.Octopus.Examples project for comprehensive examples including:
- User management system
- Email notification service
- File storage system
- Different adapter implementations
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Related Projects
- Zooper.Bee - Fluent workflow framework
- Zooper.Fox - Functional programming primitives
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.0.0 | 485 | 4/18/2025 |