Quick Start¶
Get started with DecoWeaver in 5 minutes by creating a simple logging decorator.
Step 1: Install DecoWeaver¶
Step 2: Create Your Service¶
public interface IUserService
{
Task<User> GetByIdAsync(int id);
}
public class UserService : IUserService
{
private readonly IUserRepository _repository;
public UserService(IUserRepository repository)
{
_repository = repository;
}
public async Task<User> GetByIdAsync(int id)
{
return await _repository.GetByIdAsync(id);
}
}
Step 3: Create a Decorator¶
using Microsoft.Extensions.Logging;
public class LoggingUserService : IUserService
{
private readonly IUserService _inner;
private readonly ILogger<LoggingUserService> _logger;
public LoggingUserService(
IUserService inner,
ILogger<LoggingUserService> logger)
{
_inner = inner;
_logger = logger;
}
public async Task<User> GetByIdAsync(int id)
{
_logger.LogInformation("Getting user {UserId}", id);
var user = await _inner.GetByIdAsync(id);
_logger.LogInformation(
"Retrieved user {UserId}: {UserName}",
id,
user.Name);
return user;
}
}
Step 4: Apply the Decorator Attribute¶
Add the [DecoratedBy] attribute to your implementation:
using DecoWeaver.Attributes;
[DecoratedBy<LoggingUserService>]
public class UserService : IUserService
{
// Your implementation
}
Step 5: Register in DI¶
Register your service normally - DecoWeaver handles the decoration automatically:
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
// Add logging
services.AddLogging();
// Register your service - DecoWeaver automatically applies the decorator
services.AddScoped<IUserService, UserService>();
// Build and resolve
var provider = services.BuildServiceProvider();
var userService = provider.GetRequiredService<IUserService>();
// userService is actually: LoggingUserService wrapping UserService
await userService.GetByIdAsync(123);
// Logs: "Getting user 123"
// Logs: "Retrieved user 123: John Doe"
What Just Happened?¶
- Build Time: DecoWeaver's source generator detected the
[DecoratedBy]attribute - Code Generation: Generated an interceptor that rewrites the
AddScopedcall - Runtime: Your service is automatically wrapped with the logging decorator
View Generated Code¶
To see the generated interceptor code:
Visual Studio: Solution Explorer → Show All Files → obj/Debug/net8.0/generated/DecoWeaver/
Rider: Solution Explorer → Generated Files node
Alternative: Assembly-Level Decorators¶
Instead of applying decorators to each class individually, you can apply them to all implementations from one place:
// In GlobalUsings.cs or any .cs file
using DecoWeaver.Attributes;
[assembly: DecorateService(typeof(IUserService), typeof(LoggingUserService))]
// Now ALL IUserService implementations automatically get logging
public class UserService : IUserService { }
public class AdminUserService : IUserService { }
This is ideal for cross-cutting concerns like logging, metrics, or caching that apply to many services. See Assembly-Level Decorators for details.
Next Steps¶
Now that you have a basic decorator working, explore:
- Assembly-Level Decorators - Apply decorators globally
- Multiple Decorators - Stack decorators with ordering
- Open Generics - Decorate
IRepository<T>patterns - Examples - Real-world decorator patterns
Common First-Time Issues¶
Generator Not Running?
If decorators aren't being applied:
- Check C# language version is 11+ in your .csproj
- Clean and rebuild your solution
- Check for build errors in the Error List
- View generated files to verify interceptor was created
IntelliSense Not Working?
Rebuild your solution after adding attributes. IDEs need a successful build to recognize generated code.