Myth.DependencyInjection
3.0.4
See the version list below for details.
dotnet add package Myth.DependencyInjection --version 3.0.4
NuGet\Install-Package Myth.DependencyInjection -Version 3.0.4
<PackageReference Include="Myth.DependencyInjection" Version="3.0.4" />
<PackageVersion Include="Myth.DependencyInjection" Version="3.0.4" />
<PackageReference Include="Myth.DependencyInjection" />
paket add Myth.DependencyInjection --version 3.0.4
#r "nuget: Myth.DependencyInjection, 3.0.4"
#:package Myth.DependencyInjection@3.0.4
#addin nuget:?package=Myth.DependencyInjection&version=3.0.4
#tool nuget:?package=Myth.DependencyInjection&version=3.0.4
Myth.DependencyInjection
A .NET library that simplifies dependency injection with automatic type discovery and convention-based service registration. Eliminate boilerplate code and enable plugin architectures with powerful assembly scanning and type resolution capabilities.
Features
- Type Discovery: Automatically discover and scan application assemblies and types
- Convention-based Registration: Auto-register services based on interface naming conventions
- Assembly Scanning: Load and analyze all assemblies in your application domain
- Type Filtering: Find types implementing specific interfaces or base classes
- Namespace Detection: Automatically detect your application's base namespace
- Minimal Configuration: Reduce boilerplate DI registration code
- Plugin Support: Enable plugin architectures with dynamic type loading
Installation
dotnet add package Myth.DependencyInjection
Quick Start
Automatic Service Registration
Register all implementations of an interface automatically based on naming conventions:
using Microsoft.Extensions.DependencyInjection;
using Myth.Extensions;
var services = new ServiceCollection();
// Automatically finds and registers all repository implementations
services.AddServiceFromType<IRepository>();
// Result: IPersonRepository -> PersonRepository (Scoped)
// IOrderRepository -> OrderRepository (Scoped)
// IProductRepository -> ProductRepository (Scoped)
Type Discovery
Discover and analyze types in your application:
using Myth.ValueProviders;
// Get base namespace
var baseNamespace = TypeProvider.BaseApplicationNamespace;
// Returns: "MyApp" (from MyApp.Domain, MyApp.Services, etc.)
// Get all application assemblies
var assemblies = TypeProvider.ApplicationAssemblies;
// Returns: All loaded assemblies from your application
// Get all concrete types
var types = TypeProvider.ApplicationTypes;
// Returns: All non-abstract, non-interface types
// Find types implementing specific interface
var handlers = TypeProvider.GetTypesAssignableFrom<ICommandHandler>();
// Returns: All types implementing ICommandHandler
Usage Scenarios
1. Repository Pattern Auto-Registration
Eliminate manual repository registration:
// Before: Manual registration for each repository
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IOrderRepository, OrderRepository>();
services.AddScoped<IProductRepository, ProductRepository>();
// ... dozens more
// After: One-line registration
services.AddServiceFromType<IRepository>();
Convention: The implementation class name must contain the interface name.
IUserRepository→UserRepository(valid)IOrderRepository→OrderRepository(valid)IProductRepository→ProductRepositoryImpl(valid)
2. CQRS Handler Registration
Automatically register command and query handlers:
// Register all command handlers
services.AddServiceFromType<ICommandHandler>(ServiceLifetime.Transient);
// Register all query handlers
services.AddServiceFromType<IQueryHandler>(ServiceLifetime.Transient);
// Register all event handlers
services.AddServiceFromType<IEventHandler>(ServiceLifetime.Scoped);
3. Plugin Architecture
Dynamically discover and load plugins:
// Find all plugin types
var pluginTypes = TypeProvider.GetTypesAssignableFrom<IPlugin>();
foreach (var pluginType in pluginTypes) {
var plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugin.Initialize();
Console.WriteLine($"Loaded plugin: {plugin.Name}");
}
4. Custom Service Lifetime
Specify service lifetime when registering:
// Register as Singleton
services.AddServiceFromType<ICache>(ServiceLifetime.Singleton);
// Register as Transient
services.AddServiceFromType<IValidator>(ServiceLifetime.Transient);
// Register as Scoped (default)
services.AddServiceFromType<IUnitOfWork>(ServiceLifetime.Scoped);
5. Domain-Driven Design (DDD)
Auto-register domain services and repositories:
public class Startup {
public void ConfigureServices(IServiceCollection services) {
// Infrastructure layer
services.AddServiceFromType<IRepository>(ServiceLifetime.Scoped);
// Domain services
services.AddServiceFromType<IDomainService>(ServiceLifetime.Scoped);
// Application services
services.AddServiceFromType<IApplicationService>(ServiceLifetime.Scoped);
}
}
6. Assembly Analysis and Documentation
Generate documentation about your application structure:
using Myth.ValueProviders;
public class AssemblyAnalyzer {
public void PrintApplicationStructure() {
Console.WriteLine($"Base Namespace: {TypeProvider.BaseApplicationNamespace}");
Console.WriteLine("\nAssemblies:");
foreach (var assembly in TypeProvider.ApplicationAssemblies) {
Console.WriteLine($" - {assembly.GetName().Name} v{assembly.GetName().Version}");
}
Console.WriteLine("\nService Implementations:");
var services = TypeProvider.GetTypesAssignableFrom<IService>();
foreach (var service in services) {
Console.WriteLine($" - {service.FullName}");
}
}
}
API Reference
TypeProvider
Static class for type and assembly discovery.
Properties
// Gets the first part of your application namespace
public static string? BaseApplicationNamespace { get; }
// Gets all assemblies from your application
public static IEnumerable<Assembly> ApplicationAssemblies { get; }
// Gets all concrete types exported by your application
public static IEnumerable<Type> ApplicationTypes { get; }
Methods
// Gets types derived from or implementing the specified type
public static IEnumerable<Type> GetTypesAssignableFrom<TType>()
Examples:
// Get base namespace
var ns = TypeProvider.BaseApplicationNamespace;
// "MyCompany" from "MyCompany.ECommerce.Domain"
// Get all assemblies
var assemblies = TypeProvider.ApplicationAssemblies;
// Get all types
var allTypes = TypeProvider.ApplicationTypes;
// Get types implementing interface
var repositories = TypeProvider.GetTypesAssignableFrom<IRepository>();
var handlers = TypeProvider.GetTypesAssignableFrom<IHandler>();
var validators = TypeProvider.GetTypesAssignableFrom<IValidator>();
ServiceCollectionExtensions
Extension methods for IServiceCollection.
Methods
// Adds all implementations of the specified type to the service collection
public static IServiceCollection AddServiceFromType<TType>(
this IServiceCollection services,
ServiceLifetime serviceLifetime = ServiceLifetime.Scoped
)
Parameters:
TType: The base interface or type to search for implementationsserviceLifetime: The service lifetime (Scoped, Transient, or Singleton). Default: Scoped
Returns: The service collection for chaining
Throws:
InterfaceNotFoundException: When an implementation doesn't have a corresponding interface
Naming Convention: The method finds implementations by matching the interface name within the implementation name.
- Interface:
IPersonRepository→ Implementation:PersonRepository(match: "PersonRepository") - Interface:
IOrderService→ Implementation:OrderService(match: "OrderService")
Examples:
// Scoped (default)
services.AddServiceFromType<IRepository>();
// Transient
services.AddServiceFromType<IValidator>(ServiceLifetime.Transient);
// Singleton
services.AddServiceFromType<ICache>(ServiceLifetime.Singleton);
Best Practices
1. Organize by Layers
Structure your DI registration by architectural layer:
public void ConfigureServices(IServiceCollection services) {
// Persistence Layer
services.AddServiceFromType<IRepository>(ServiceLifetime.Scoped);
// Domain Layer
services.AddServiceFromType<IDomainService>(ServiceLifetime.Scoped);
// Application Layer
services.AddServiceFromType<IApplicationService>(ServiceLifetime.Scoped);
// Infrastructure Layer
services.AddServiceFromType<IExternalService>(ServiceLifetime.Transient);
}
2. Use Marker Interfaces
Create marker interfaces for auto-registration:
// Marker interface for domain services
public interface IDomainService { }
public interface IOrderService : IDomainService {
Task<Order> CreateOrderAsync(CreateOrderCommand command);
}
public class OrderService : IOrderService {
public async Task<Order> CreateOrderAsync(CreateOrderCommand command) {
// Implementation
}
}
// Auto-register all domain services
services.AddServiceFromType<IDomainService>();
3. Follow Naming Conventions
Ensure consistent naming for automatic discovery:
// Good: Name matches interface
public interface IUserRepository { }
public class UserRepository : IUserRepository { }
// Good: Implementation name contains interface name
public interface IProductRepository { }
public class ProductRepositoryImpl : IProductRepository { }
// Bad: No naming correlation
public interface IOrderRepository { }
public class OrderDataAccess : IOrderRepository { } // Won't be auto-discovered
4. Combine with Manual Registration
Use auto-registration for conventions, manual for exceptions:
// Auto-register most services
services.AddServiceFromType<IRepository>();
services.AddServiceFromType<IService>();
// Manually register special cases
services.AddSingleton<IConfiguration>(configuration);
services.AddScoped<ICurrentUser, CurrentUserAccessor>();
services.AddTransient<IEmailSender, SendGridEmailSender>();
5. Validate Registrations
Check that types were registered correctly:
var serviceProvider = services.BuildServiceProvider();
// Verify critical services are registered
var userRepo = serviceProvider.GetService<IUserRepository>();
if (userRepo == null) {
throw new InvalidOperationException("IUserRepository not registered");
}
// Or use GetRequiredService to throw if not found
var orderService = serviceProvider.GetRequiredService<IOrderService>();
How It Works
Type Discovery Process
- Assembly Loading: Scans
AppDomain.CurrentDomain.BaseDirectoryfor all.dllfiles - Dynamic Loading: Loads assemblies not yet loaded into the current AppDomain
- Filtering: Excludes dynamic assemblies and keeps only concrete types
- Caching: Results are computed once per property access for performance
Auto-Registration Process
- Type Scanning: Finds all types implementing the specified base type/interface
- Interface Matching: For each implementation, finds the corresponding interface by name
- Registration: Creates a
ServiceDescriptorand adds to the service collection - Validation: Throws
InterfaceNotFoundExceptionif no matching interface is found
Performance Considerations
- Assembly Scanning: Performed once per
ApplicationAssembliesaccess; results are not cached between accesses - Type Discovery: Filters are applied efficiently using LINQ
- Registration Time: Auto-registration happens at application startup, not runtime
- Large Codebases: For applications with hundreds of assemblies, consider manual registration for critical paths
Integration with Other Myth Libraries
Myth.DependencyInjection works seamlessly with other Myth libraries:
using Myth.Extensions;
using Myth.ValueProviders;
var builder = WebApplication.CreateBuilder(args);
// Auto-register repositories (Myth.Repository)
builder.Services.AddServiceFromType<IRepository>();
// Add Flow pipeline support (Myth.Flow)
builder.Services.AddFlow();
// Add Guard validation (Myth.Guard)
builder.Services.AddGuard();
// Build with global provider support
var app = builder.BuildApp();
app.Run();
Troubleshooting
InterfaceNotFoundException
Problem: InterfaceNotFoundException: Not found a interface that corresponds to type
Solution: Ensure your implementation class name contains the interface name:
// Problematic
public interface IUserRepository { }
public class UserDataAccess : IUserRepository { } // Name doesn't contain "IUserRepository"
// Fixed
public interface IUserRepository { }
public class UserRepository : IUserRepository { } // Contains "UserRepository"
Types Not Discovered
Problem: Expected types are not found by GetTypesAssignableFrom<T>()
Solution:
- Ensure the assembly is loaded (referenced in your project)
- Verify types are concrete (not abstract or interfaces)
- Check that types are public and accessible
Multiple Interfaces per Implementation
Problem: A class implements multiple interfaces
Solution: The auto-registration finds the first interface containing the class name. For precise control, register manually:
// Auto-registration picks one interface
services.AddServiceFromType<IService>();
// Manual registration for multiple interfaces
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IReadOnlyUserRepository, UserRepository>();
License
This project is licensed under the Apache 2.0 License - see the LICENSE for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Related Libraries
- Myth.Flow: Pipeline orchestration with Result pattern
- Myth.Flow.Actions: CQRS and event-driven architecture
- Myth.Guard: Fluent validation and data integrity
- Myth.Repository: Generic repository pattern implementation
- Myth.Specification: Query specification pattern
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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. |
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
- Myth.Commons (>= 3.0.4)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Myth.DependencyInjection:
| Package | Downloads |
|---|---|
|
Myth.Repository.EntityFramework
Entity Framework Core implementations of repository pattern with Unit of Work, specification support, expression handling, and transaction management for robust data access with EF Core. |
|
|
Harpy.IoC
Basis for the ioc layer of the Harpy Framework |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.5-preview.14 | 24 | 11/12/2025 |
| 3.0.5-preview.13 | 41 | 11/12/2025 |
| 3.0.5-preview.12 | 36 | 11/11/2025 |
| 3.0.5-preview.11 | 35 | 11/11/2025 |
| 3.0.5-preview.10 | 35 | 11/11/2025 |
| 3.0.5-preview.9 | 43 | 11/10/2025 |
| 3.0.5-preview.8 | 46 | 11/8/2025 |
| 3.0.5-preview.7 | 46 | 11/8/2025 |
| 3.0.5-preview.6 | 47 | 11/8/2025 |
| 3.0.5-preview.5 | 48 | 11/8/2025 |
| 3.0.5-preview.4 | 48 | 11/7/2025 |
| 3.0.5-preview.3 | 127 | 11/4/2025 |
| 3.0.5-preview.2 | 125 | 11/4/2025 |
| 3.0.5-preview.1 | 126 | 11/4/2025 |
| 3.0.4 | 204 | 11/3/2025 |
| 3.0.4-preview.19 | 68 | 11/2/2025 |
| 3.0.4-preview.18 | 63 | 11/1/2025 |
| 3.0.4-preview.17 | 65 | 11/1/2025 |
| 3.0.4-preview.16 | 65 | 11/1/2025 |
| 3.0.4-preview.15 | 61 | 10/31/2025 |
| 3.0.4-preview.14 | 128 | 10/31/2025 |
| 3.0.4-preview.13 | 127 | 10/30/2025 |
| 3.0.4-preview.12 | 125 | 10/23/2025 |
| 3.0.4-preview.11 | 119 | 10/23/2025 |
| 3.0.4-preview.10 | 120 | 10/23/2025 |
| 3.0.4-preview.9 | 118 | 10/23/2025 |
| 3.0.4-preview.8 | 112 | 10/22/2025 |
| 3.0.4-preview.6 | 112 | 10/21/2025 |
| 3.0.4-preview.5 | 112 | 10/21/2025 |
| 3.0.4-preview.4 | 117 | 10/20/2025 |
| 3.0.4-preview.3 | 117 | 10/20/2025 |
| 3.0.4-preview.2 | 38 | 10/18/2025 |
| 3.0.4-preview.1 | 125 | 10/7/2025 |
| 3.0.3 | 220 | 8/30/2025 |
| 3.0.2 | 116 | 8/23/2025 |
| 3.0.2-preview.4 | 122 | 8/21/2025 |
| 3.0.2-preview.3 | 102 | 8/16/2025 |
| 3.0.2-preview.1 | 72 | 5/23/2025 |
| 3.0.1 | 236 | 3/12/2025 |
| 3.0.1-preview.2 | 146 | 3/11/2025 |
| 3.0.1-preview.1 | 92 | 2/5/2025 |
| 3.0.0.2-preview | 139 | 12/10/2024 |
| 3.0.0.1-preview | 169 | 6/29/2024 |
| 3.0.0 | 179 | 12/10/2024 |
| 3.0.0-preview | 166 | 6/28/2024 |
| 2.0.0.16 | 297 | 12/15/2023 |
| 2.0.0.15 | 195 | 12/15/2023 |
| 2.0.0.11 | 1,359 | 8/11/2022 |
| 2.0.0.10 | 1,317 | 7/20/2022 |
| 2.0.0.9 | 1,384 | 7/15/2022 |
| 2.0.0.8 | 1,373 | 7/12/2022 |
| 2.0.0.7 | 1,408 | 6/20/2022 |
| 2.0.0.6 | 1,451 | 5/23/2022 |
| 2.0.0.5 | 1,435 | 5/18/2022 |