Basic Example
This example demonstrates the basic usage of Contexify, including creating a context, binding services, and using dependency injection.
Complete Example
import { Context, injectable, inject } from 'contexify';
// Define interfaces
interface Logger {
log(message: string): void;
}
interface UserService {
createUser(name: string): Promise<User>;
}
interface User {
id: string;
name: string;
}
// Implement services
@injectable()
class ConsoleLogger implements Logger {
log(message: string) {
console.log(`[LOG] ${message}`);
}
}
@injectable()
class DefaultUserService implements UserService {
constructor(@inject('services.Logger') private logger: Logger) {}
async createUser(name: string): Promise<User> {
this.logger.log(`Creating user: ${name}`);
return { id: Date.now().toString(), name };
}
}
// Create a context
const context = new Context('application');
// Bind services
context.bind('services.Logger').toClass(ConsoleLogger);
context.bind('services.UserService').toClass(DefaultUserService);
// Use services
async function run() {
const userService = await context.get<UserService>('services.UserService');
const user = await userService.createUser('John Doe');
console.log('Created user:', user);
}
run().catch(err => console.error(err));
Step-by-Step Explanation
1. Define Interfaces
First, we define interfaces for our services:
interface Logger {
log(message: string): void;
}
interface UserService {
createUser(name: string): Promise<User>;
}
interface User {
id: string;
name: string;
}
Defining interfaces helps with loose coupling and better testability.
2. Implement Services
Next, we implement our services:
@injectable()
class ConsoleLogger implements Logger {
log(message: string) {
console.log(`[LOG] ${message}`);
}
}
@injectable()
class DefaultUserService implements UserService {
constructor(@inject('services.Logger') private logger: Logger) {}
async createUser(name: string): Promise<User> {
this.logger.log(`Creating user: ${name}`);
return { id: Date.now().toString(), name };
}
}
Note:
- The
@injectable()
decorator marks the class as injectable - The
@inject('services.Logger')
decorator injects the Logger service
3. Create a Context
Then, we create a context:
const context = new Context('application');
4. Bind Services
We bind our services to the context:
context.bind('services.Logger').toClass(ConsoleLogger);
context.bind('services.UserService').toClass(DefaultUserService);
5. Use Services
Finally, we get the service from the context and use it:
async function run() {
const userService = await context.get<UserService>('services.UserService');
const user = await userService.createUser('John Doe');
console.log('Created user:', user);
}
run().catch(err => console.error(err));
Key Points
- Dependency Injection:
UserService
depends onLogger
through constructor injection - Inversion of Control: The creation and lifecycle of services are managed by the Context
- Loose Coupling: Services interact through interfaces rather than concrete implementations
Next Steps
Check out more advanced examples: