Analyze project structure and Composer patterns in Umbraco projects
Analyzes Umbraco project structure, Composer patterns, and service registration for architectural issues.
/plugin marketplace add twofoldtech-dakota/claude-marketplace/plugin install twofoldtech-dakota-umbraco-analyzer-plugins-umbraco-analyzer@twofoldtech-dakota/claude-marketplaceAnalyze project structure, Composer implementations, and service registration patterns.
Check for proper Composer implementations:
// Good: Focused Composer
public class MyServicesComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddScoped<IMyService, MyService>();
builder.Services.AddScoped<IOtherService, OtherService>();
}
}
Flag if Composer has >10 registrations (ARCH-002).
Check for appropriate lifetimes:
// Correct lifetimes
services.AddSingleton<ICacheService, CacheService>(); // Stateless cache
services.AddScoped<IContentService, ContentService>(); // Per-request
services.AddTransient<IEmailSender, EmailSender>(); // Stateless utility
Detect direct service location:
// Anti-pattern
var service = serviceProvider.GetService<IMyService>();
var service = HttpContext.RequestServices.GetService<IMyService>();
// Good: Constructor injection
public class MyController : Controller
{
private readonly IMyService _myService;
public MyController(IMyService myService)
{
_myService = myService;
}
}
Check for proper notification handler setup:
// Good: Handler with single responsibility
public class ContentPublishedHandler : INotificationHandler<ContentPublishedNotification>
{
public Task HandleAsync(ContentPublishedNotification notification, CancellationToken ct)
{
// Handle single concern
return Task.CompletedTask;
}
}
// Registration in Composer
builder.AddNotificationHandler<ContentPublishedNotification, ContentPublishedHandler>();
Check for circular references in service registration:
// Circular dependency
public class ServiceA
{
public ServiceA(ServiceB b) { }
}
public class ServiceB
{
public ServiceB(ServiceA a) { } // Circular!
}
Check controller complexity:
// Warning: Fat controller (>5 actions)
public class ProductController : SurfaceController
{
public IActionResult Index() { }
public IActionResult Details() { }
public IActionResult Create() { }
public IActionResult Edit() { }
public IActionResult Delete() { }
public IActionResult Search() { }
public IActionResult Filter() { } // Too many!
}
Check for proper layer separation:
Good:
src/
├── Web/ # Controllers, Views, Composers
├── Core/ # Business logic, interfaces
└── Infrastructure/ # Data access, external services
Bad:
MyUmbracoSite/
├── Everything mixed together
| Code | Severity | Issue | Detection |
|---|---|---|---|
| ARCH-001 | Critical | Service Locator pattern | GetService<>() outside Composer |
| ARCH-002 | Warning | Composer too large | >10 registrations in single Composer |
| ARCH-003 | Warning | Circular dependency | Mutual constructor injection |
| ARCH-004 | Warning | Fat controller | Controller with >5 actions |
| ARCH-005 | Info | Missing interface | Service without interface |
| ARCH-006 | Info | Incorrect lifetime | Scoped service in singleton |
Grep: : IComposer
Grep: IUmbracoBuilder
Count registrations per Composer
Grep: \.GetService<
Grep: \.GetRequiredService<
Grep: ServiceProvider\.
Exclude Composer files
Glob: **/Controllers/**/*.cs
Count public action methods per controller
For each service class:
Extract constructor parameters
Build dependency graph
Detect cycles
## Architecture Analysis
### Summary
- **Composers Found**: 5
- **Services Registered**: 23
- **Controllers**: 8
- **Architecture Score**: B+
### Critical Issues
#### [ARCH-001] Service Locator Pattern
**Location**: `src/Web/Services/LegacyService.cs:45`
**Code**:
```csharp
var service = _serviceProvider.GetService<IContentService>();
Fix: Inject IContentService via constructor
Location: src/Web/Composers/MainComposer.cs
Issue: 18 service registrations in single Composer
Fix: Split into focused Composers:
ServicesComposer - Business servicesRepositoriesComposer - Data accessNotificationsComposer - Event handlersLocation: src/Web/Controllers/ProductController.cs
Issue: 8 actions in single controller
Fix: Split into:
ProductController - CRUD operationsProductSearchController - Search/filter| Composer | Registrations | Status |
|---|---|---|
| ServicesComposer | 5 | Good |
| MainComposer | 18 | Warning |
| NotificationsComposer | 3 | Good |