dire_di 1.0.1 copy "dire_di: ^1.0.1" to clipboard
dire_di: ^1.0.1 copied to clipboard

A Spring-like dependency injection framework for Dart with auto-wiring capabilities using mirrors.

example/main.dart

import 'package:dire_di/dire_di.dart';

// Model classes
class User {
  final int id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  @override
  String toString() => 'User(id: $id, name: $name, email: $email)';
}

// Repository layer
@Repository()
class UserRepository {
  final List<User> _users = [
    User(id: 1, name: 'John Doe', email: 'john@example.com'),
    User(id: 2, name: 'Jane Smith', email: 'jane@example.com'),
    User(id: 3, name: 'Bob Johnson', email: 'bob@example.com'),
  ];

  Future<User?> findById(int id) async {
    // Simulate database delay
    await Future.delayed(Duration(milliseconds: 100));

    try {
      return _users.firstWhere((user) => user.id == id);
    } catch (e) {
      return null;
    }
  }

  Future<List<User>> findAll() async {
    // Simulate database delay
    await Future.delayed(Duration(milliseconds: 150));
    return List.from(_users);
  }

  Future<void> save(User user) async {
    await Future.delayed(Duration(milliseconds: 200));
    final index = _users.indexWhere((u) => u.id == user.id);
    if (index != -1) {
      _users[index] = user;
    } else {
      _users.add(user);
    }
  }
}

// Service layer
@Service()
class UserService {
  @Autowired()
  late UserRepository userRepository;

  @Autowired()
  late EmailService emailService;

  Future<User?> getUser(int id) async {
    print('UserService: Getting user with id $id');
    return await userRepository.findById(id);
  }

  Future<List<User>> getAllUsers() async {
    print('UserService: Getting all users');
    return await userRepository.findAll();
  }

  Future<void> createUser(String name, String email) async {
    final newId = DateTime.now().millisecondsSinceEpoch;
    final user = User(id: newId, name: name, email: email);

    await userRepository.save(user);
    await emailService.sendWelcomeEmail(user);

    print('UserService: Created user $user');
  }
}

// Email service interface
abstract class EmailService {
  Future<void> sendWelcomeEmail(User user);
  Future<void> sendNotification(User user, String message);
}

// Development email service
@Service()
@Profile('development')
@Qualifier('dev')
class DevEmailService implements EmailService {
  @override
  Future<void> sendWelcomeEmail(User user) async {
    print('DEV EMAIL: Welcome ${user.name}! Your account has been created.');
  }

  @override
  Future<void> sendNotification(User user, String message) async {
    print('DEV EMAIL: ${user.name}, you have a notification: $message');
  }
}

// Production email service
@Service()
@Profile('production')
@Qualifier('prod')
class ProdEmailService implements EmailService {
  @override
  Future<void> sendWelcomeEmail(User user) async {
    // In production, this would send a real email
    await Future.delayed(Duration(milliseconds: 500));
    print('PROD EMAIL: Sent welcome email to ${user.email}');
  }

  @override
  Future<void> sendNotification(User user, String message) async {
    // In production, this would send a real email
    await Future.delayed(Duration(milliseconds: 300));
    print('PROD EMAIL: Sent notification to ${user.email}: $message');
  }
}

// Default email service when no profile matches
@Service()
@ConditionalOnMissingBean(EmailService)
class DefaultEmailService implements EmailService {
  @override
  Future<void> sendWelcomeEmail(User user) async {
    print('DEFAULT EMAIL: Welcome ${user.name}!');
  }

  @override
  Future<void> sendNotification(User user, String message) async {
    print('DEFAULT EMAIL: ${user.name}: $message');
  }
}

// Controller layer
@Controller()
class UserController {
  @Autowired()
  late UserService userService;

  Future<void> handleGetUser(int id) async {
    try {
      final user = await userService.getUser(id);
      if (user != null) {
        print('Controller: Found user: $user');
      } else {
        print('Controller: User with id $id not found');
      }
    } catch (e) {
      print('Controller: Error getting user: $e');
    }
  }

  Future<void> handleGetAllUsers() async {
    try {
      final users = await userService.getAllUsers();
      print('Controller: Found ${users.length} users:');
      for (final user in users) {
        print('  - $user');
      }
    } catch (e) {
      print('Controller: Error getting users: $e');
    }
  }

  Future<void> handleCreateUser(String name, String email) async {
    try {
      await userService.createUser(name, email);
      print('Controller: User created successfully');
    } catch (e) {
      print('Controller: Error creating user: $e');
    }
  }
}

// Configuration class example
@Configuration()
class AppConfig {
  @Bean()
  @Singleton()
  Map<String, String> createAppProperties() {
    return {
      'app.name': 'Dire DI Example',
      'app.version': '1.0.0',
      'feature.email.enabled': 'true',
    };
  }

  @Bean()
  @Qualifier('logger')
  Logger createLogger() {
    return Logger('DireApp');
  }
}

// Simple logger class
class Logger {
  final String name;

  Logger(this.name);

  void info(String message) {
    print('[$name] INFO: $message');
  }

  void error(String message, [Object? error]) {
    print('[$name] ERROR: $message ${error ?? ''}');
  }
}

// Main application
void main() async {
  print('=== Dire DI Example Application ===\n');

  try {
    // Create container with development profile
    final container = DireContainer(
      activeProfiles: ['development'],
      properties: {
        'feature.email.enabled': 'true',
        'app.env': 'development',
      },
    );

    // Scan for components
    print('Scanning for components...');
    await container.scan();
    print('Container initialized successfully!\n');

    // Get the controller
    final controller = container.get<UserController>();

    // Test getting a user
    print('=== Test: Get User by ID ===');
    await controller.handleGetUser(1);
    await controller.handleGetUser(999); // Non-existent user
    print('');

    // Test getting all users
    print('=== Test: Get All Users ===');
    await controller.handleGetAllUsers();
    print('');

    // Test creating a user
    print('=== Test: Create New User ===');
    await controller.handleCreateUser('Alice Wilson', 'alice@example.com');
    print('');

    // Test getting all users again to see the new user
    print('=== Test: Get All Users (After Creation) ===');
    await controller.handleGetAllUsers();
    print('');

    // Test getting beans by qualifier
    print('=== Test: Get Logger Bean ===');
    final logger = container.getByName('logger') as Logger;
    logger.info('Application started successfully');
    print('');

    // Test getting properties bean
    print('=== Test: Get Properties Bean ===');
    final properties = container.get<Map<String, String>>();
    print('App properties:');
    properties.forEach((key, value) => print('  $key: $value'));
    print('');

    // Test multiple email services
    print('=== Test: Multiple Email Services ===');
    final emailServices = container.getAll<EmailService>();
    print('Found ${emailServices.length} email service(s):');
    for (int i = 0; i < emailServices.length; i++) {
      final service = emailServices[i];
      print('  ${i + 1}. ${service.runtimeType}');
    }
  } catch (e, stackTrace) {
    print('Application failed to start: $e');
    print('Stack trace: $stackTrace');
  }
}
1
likes
150
points
28
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Spring-like dependency injection framework for Dart with auto-wiring capabilities using mirrors.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

collection, meta

More

Packages that depend on dire_di