add: adding container to platform
This commit is contained in:
parent
933321f13f
commit
6ff734bdf7
14 changed files with 2985 additions and 0 deletions
126
packages/container/example/README.md
Normal file
126
packages/container/example/README.md
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
# Laravel Container Examples
|
||||||
|
|
||||||
|
These examples demonstrate how to use the Laravel-style dependency injection container in Dart.
|
||||||
|
|
||||||
|
## Basic Container Features (container_usage.dart)
|
||||||
|
|
||||||
|
Shows core container features using a payment processing example:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// Basic binding
|
||||||
|
container.bind<PaymentGateway>((c) => StripeGateway(c.make<String>()));
|
||||||
|
|
||||||
|
// Singleton registration
|
||||||
|
container.singleton<PaymentService>((c) => PaymentService(c.make<PaymentGateway>()));
|
||||||
|
|
||||||
|
// Contextual binding
|
||||||
|
container.when(PaymentService)
|
||||||
|
.needs<PaymentGateway>()
|
||||||
|
.give(PayPalGateway());
|
||||||
|
|
||||||
|
// Tagged services
|
||||||
|
container.tag([StripeGateway, PayPalGateway], 'gateways');
|
||||||
|
final gateways = container.tagged<PaymentGateway>('gateways');
|
||||||
|
|
||||||
|
// Instance extending
|
||||||
|
container.extend(PaymentGateway, (gateway) {
|
||||||
|
print('Payment gateway was created');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
```bash
|
||||||
|
dart run container_usage.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Container Features (advanced_usage.dart)
|
||||||
|
|
||||||
|
Demonstrates advanced container capabilities:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// Child containers
|
||||||
|
final rootContainer = IlluminateContainer(reflector);
|
||||||
|
rootContainer.singleton<Logger>((c) => ProductionLogger());
|
||||||
|
|
||||||
|
final testContainer = rootContainer.createChild();
|
||||||
|
testContainer.singleton<Logger>((c) => TestLogger());
|
||||||
|
|
||||||
|
// Scoped bindings
|
||||||
|
container.scoped<RequestScope>((c) => RequestScope());
|
||||||
|
container.bind<UserRepository>((c) => UserRepository(
|
||||||
|
c.make<Logger>(),
|
||||||
|
c.make<RequestScope>()
|
||||||
|
));
|
||||||
|
|
||||||
|
// Scope lifecycle
|
||||||
|
final repo1 = container.make<UserRepository>();
|
||||||
|
final repo2 = container.make<UserRepository>();
|
||||||
|
assert(identical(repo1.scope, repo2.scope)); // Same scope
|
||||||
|
|
||||||
|
container.forgetScopedInstances(); // Clear scope
|
||||||
|
|
||||||
|
final repo3 = container.make<UserRepository>();
|
||||||
|
assert(!identical(repo1.scope, repo3.scope)); // New scope
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
```bash
|
||||||
|
dart run advanced_usage.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Application Architecture (app_example.dart)
|
||||||
|
|
||||||
|
Shows how to use the container in a real application:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// Register repositories
|
||||||
|
container.singleton<UserRepository>((c) => DatabaseUserRepository());
|
||||||
|
|
||||||
|
// Register services
|
||||||
|
container.singleton<EmailService>((c) => EmailService());
|
||||||
|
container.singleton<UserService>((c) => UserService(
|
||||||
|
c.make<UserRepository>(),
|
||||||
|
c.make<EmailService>()
|
||||||
|
));
|
||||||
|
|
||||||
|
// Register controllers
|
||||||
|
container.singleton<UserController>((c) => UserController(
|
||||||
|
c.make<UserService>()
|
||||||
|
));
|
||||||
|
|
||||||
|
// Use the application
|
||||||
|
final controller = container.make<UserController>();
|
||||||
|
controller.createUser('John Doe', 'john@example.com');
|
||||||
|
```
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
```bash
|
||||||
|
dart run app_example.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Features Demonstrated
|
||||||
|
|
||||||
|
1. Dependency Registration
|
||||||
|
- Basic bindings
|
||||||
|
- Singleton registration
|
||||||
|
- Factory bindings
|
||||||
|
- Instance registration
|
||||||
|
- Scoped bindings
|
||||||
|
|
||||||
|
2. Service Resolution
|
||||||
|
- Automatic dependency injection
|
||||||
|
- Contextual binding
|
||||||
|
- Tagged services
|
||||||
|
- Instance extending
|
||||||
|
|
||||||
|
3. Container Features
|
||||||
|
- Child containers
|
||||||
|
- Scope management
|
||||||
|
- Service location
|
||||||
|
- Interface binding
|
||||||
|
|
||||||
|
4. Architecture Patterns
|
||||||
|
- Repository pattern
|
||||||
|
- Service layer
|
||||||
|
- Dependency injection
|
||||||
|
- Interface segregation
|
111
packages/container/example/advanced_usage.dart
Normal file
111
packages/container/example/advanced_usage.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
|
||||||
|
// Example services
|
||||||
|
abstract class Logger {
|
||||||
|
void log(String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProductionLogger implements Logger {
|
||||||
|
@override
|
||||||
|
void log(String message) => print('PROD: $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestLogger implements Logger {
|
||||||
|
@override
|
||||||
|
void log(String message) => print('TEST: $message');
|
||||||
|
}
|
||||||
|
|
||||||
|
class RequestScope {
|
||||||
|
final String id = DateTime.now().toIso8601String();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'RequestScope($id)';
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserRepository {
|
||||||
|
final Logger logger;
|
||||||
|
final RequestScope scope;
|
||||||
|
|
||||||
|
UserRepository(this.logger, this.scope);
|
||||||
|
|
||||||
|
void save(String userId) {
|
||||||
|
logger.log('[${scope.id}] Saving user: $userId');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Create root container
|
||||||
|
final container = IlluminateContainer(ExampleReflector());
|
||||||
|
|
||||||
|
print('1. Child Containers');
|
||||||
|
print('------------------');
|
||||||
|
// Register production logger in root
|
||||||
|
container.singleton<Logger>((c) => ProductionLogger());
|
||||||
|
|
||||||
|
// Create child container with test logger
|
||||||
|
final testContainer = container.createChild();
|
||||||
|
testContainer.singleton<Logger>((c) => TestLogger());
|
||||||
|
|
||||||
|
// Use both containers
|
||||||
|
container.make<Logger>().log('Using production logger');
|
||||||
|
testContainer.make<Logger>().log('Using test logger');
|
||||||
|
container.make<Logger>().log('Still using production logger');
|
||||||
|
|
||||||
|
print('\n2. Scoped Bindings');
|
||||||
|
print('-----------------');
|
||||||
|
// Register scoped request
|
||||||
|
container.scoped<RequestScope>((c) {
|
||||||
|
final scope = RequestScope();
|
||||||
|
print('Created new scope: $scope');
|
||||||
|
return scope;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register repository that uses scope
|
||||||
|
container.bind<UserRepository>(
|
||||||
|
(c) => UserRepository(c.make<Logger>(), c.make<RequestScope>()));
|
||||||
|
|
||||||
|
print('\nFirst request:');
|
||||||
|
// Same scope within request
|
||||||
|
final repo1 = container.make<UserRepository>();
|
||||||
|
final repo2 = container.make<UserRepository>();
|
||||||
|
repo1.save('user1');
|
||||||
|
repo2.save('user2');
|
||||||
|
|
||||||
|
// Verify same scope
|
||||||
|
print('Using same scope: ${identical(repo1.scope, repo2.scope)}');
|
||||||
|
|
||||||
|
print('\nNew request:');
|
||||||
|
// Clear scope
|
||||||
|
container.forgetScopedInstances();
|
||||||
|
|
||||||
|
// New scope for new request
|
||||||
|
final repo3 = container.make<UserRepository>();
|
||||||
|
repo3.save('user3');
|
||||||
|
|
||||||
|
// Verify different scope
|
||||||
|
print('Using different scope: ${!identical(repo1.scope, repo3.scope)}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Example reflector implementation
|
||||||
|
class ExampleReflector implements ReflectorContract {
|
||||||
|
@override
|
||||||
|
String? getName(Symbol symbol) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClassContract? reflectClass(Type clazz) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunctionContract? reflectFunction(Function function) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstanceContract? reflectInstance(Object object) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract reflectFutureOf(Type type) {
|
||||||
|
throw UnsupportedError('Future reflection not needed for example');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract? reflectType(Type type) => null;
|
||||||
|
}
|
134
packages/container/example/app_example.dart
Normal file
134
packages/container/example/app_example.dart
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
|
||||||
|
// Domain Models
|
||||||
|
class User {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
final String email;
|
||||||
|
|
||||||
|
User(this.id, this.name, this.email);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repository Layer
|
||||||
|
abstract class UserRepository {
|
||||||
|
User? findById(String id);
|
||||||
|
void save(User user);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DatabaseUserRepository implements UserRepository {
|
||||||
|
final Map<String, User> _users = {};
|
||||||
|
|
||||||
|
@override
|
||||||
|
User? findById(String id) => _users[id];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void save(User user) {
|
||||||
|
print('DB: Saving user ${user.id}');
|
||||||
|
_users[user.id] = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service Layer
|
||||||
|
class UserService {
|
||||||
|
final UserRepository repository;
|
||||||
|
final EmailService emailService;
|
||||||
|
|
||||||
|
UserService(this.repository, this.emailService);
|
||||||
|
|
||||||
|
void registerUser(String name, String email) {
|
||||||
|
// Create user
|
||||||
|
final user =
|
||||||
|
User(DateTime.now().millisecondsSinceEpoch.toString(), name, email);
|
||||||
|
|
||||||
|
// Save user
|
||||||
|
repository.save(user);
|
||||||
|
|
||||||
|
// Send welcome email
|
||||||
|
emailService.sendWelcomeEmail(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
User? getUser(String id) => repository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailService {
|
||||||
|
void sendWelcomeEmail(User user) {
|
||||||
|
print('Sending welcome email to ${user.email}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller Layer
|
||||||
|
class UserController {
|
||||||
|
final UserService userService;
|
||||||
|
|
||||||
|
UserController(this.userService);
|
||||||
|
|
||||||
|
void createUser(String name, String email) {
|
||||||
|
try {
|
||||||
|
userService.registerUser(name, email);
|
||||||
|
print('User created successfully');
|
||||||
|
} catch (e) {
|
||||||
|
print('Error creating user: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getUser(String id) {
|
||||||
|
final user = userService.getUser(id);
|
||||||
|
if (user != null) {
|
||||||
|
print('Found user: ${user.name} (${user.email})');
|
||||||
|
} else {
|
||||||
|
print('User not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Create container
|
||||||
|
final container = IlluminateContainer(ExampleReflector());
|
||||||
|
|
||||||
|
// Register repositories
|
||||||
|
container.singleton<UserRepository>((c) => DatabaseUserRepository());
|
||||||
|
|
||||||
|
// Register services
|
||||||
|
container.singleton<EmailService>((c) => EmailService());
|
||||||
|
container.singleton<UserService>(
|
||||||
|
(c) => UserService(c.make<UserRepository>(), c.make<EmailService>()));
|
||||||
|
|
||||||
|
// Register controllers
|
||||||
|
container
|
||||||
|
.singleton<UserController>((c) => UserController(c.make<UserService>()));
|
||||||
|
|
||||||
|
// Use the application
|
||||||
|
final controller = container.make<UserController>();
|
||||||
|
|
||||||
|
// Create a user
|
||||||
|
print('Creating user...');
|
||||||
|
controller.createUser('John Doe', 'john@example.com');
|
||||||
|
|
||||||
|
// Try to find the user
|
||||||
|
print('\nLooking up user...');
|
||||||
|
controller.getUser('123'); // Not found
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Example reflector implementation
|
||||||
|
class ExampleReflector implements ReflectorContract {
|
||||||
|
@override
|
||||||
|
String? getName(Symbol symbol) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClassContract? reflectClass(Type clazz) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunctionContract? reflectFunction(Function function) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstanceContract? reflectInstance(Object object) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract reflectFutureOf(Type type) {
|
||||||
|
throw UnsupportedError('Future reflection not needed for example');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract? reflectType(Type type) => null;
|
||||||
|
}
|
120
packages/container/example/container_usage.dart
Normal file
120
packages/container/example/container_usage.dart
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
|
||||||
|
// Example services
|
||||||
|
abstract class PaymentGateway {
|
||||||
|
void processPayment(double amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
class StripeGateway implements PaymentGateway {
|
||||||
|
final String apiKey;
|
||||||
|
|
||||||
|
StripeGateway(this.apiKey);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void processPayment(double amount) {
|
||||||
|
print('Stripe: Processing \$$amount');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PayPalGateway implements PaymentGateway {
|
||||||
|
@override
|
||||||
|
void processPayment(double amount) {
|
||||||
|
print('PayPal: Processing \$$amount');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaymentService {
|
||||||
|
final PaymentGateway gateway;
|
||||||
|
|
||||||
|
PaymentService(this.gateway);
|
||||||
|
|
||||||
|
void pay(double amount) {
|
||||||
|
print('Payment requested');
|
||||||
|
gateway.processPayment(amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Create container
|
||||||
|
final container = IlluminateContainer(ExampleReflector());
|
||||||
|
|
||||||
|
print('1. Basic Binding');
|
||||||
|
// Register API key
|
||||||
|
container.instance<String>('stripe-key-123');
|
||||||
|
|
||||||
|
// Register payment gateway
|
||||||
|
container.bind<PaymentGateway>((c) => StripeGateway(c.make<String>()));
|
||||||
|
|
||||||
|
// Use the gateway
|
||||||
|
final gateway = container.make<PaymentGateway>();
|
||||||
|
gateway.processPayment(99.99);
|
||||||
|
|
||||||
|
print('\n2. Singleton');
|
||||||
|
// Register payment service as singleton
|
||||||
|
container.singleton<PaymentService>(
|
||||||
|
(c) => PaymentService(c.make<PaymentGateway>()));
|
||||||
|
|
||||||
|
// Get same instance twice
|
||||||
|
final service1 = container.make<PaymentService>();
|
||||||
|
final service2 = container.make<PaymentService>();
|
||||||
|
print('Same instance: ${identical(service1, service2)}');
|
||||||
|
|
||||||
|
print('\n3. Contextual Binding');
|
||||||
|
// Use PayPal for specific service
|
||||||
|
container.when(PaymentService).needs<PaymentGateway>().give(PayPalGateway());
|
||||||
|
|
||||||
|
// New service uses PayPal
|
||||||
|
final paypalService = container.make<PaymentService>();
|
||||||
|
paypalService.pay(49.99);
|
||||||
|
|
||||||
|
print('\n4. Tagged Services');
|
||||||
|
// Register concrete implementations
|
||||||
|
container.bind<StripeGateway>((c) => StripeGateway(c.make<String>()));
|
||||||
|
container.bind<PayPalGateway>((c) => PayPalGateway());
|
||||||
|
|
||||||
|
// Tag payment gateways
|
||||||
|
container.tag([StripeGateway, PayPalGateway], 'gateways');
|
||||||
|
|
||||||
|
// Get all gateways
|
||||||
|
final gateways = container.tagged<PaymentGateway>('gateways');
|
||||||
|
print('Found ${gateways.length} payment gateways');
|
||||||
|
|
||||||
|
// Use each gateway
|
||||||
|
for (final gateway in gateways) {
|
||||||
|
gateway.processPayment(29.99);
|
||||||
|
}
|
||||||
|
|
||||||
|
print('\n5. Extending Instances');
|
||||||
|
// Add logging to payment gateway
|
||||||
|
container.extend(PaymentGateway, (gateway) {
|
||||||
|
print('Payment gateway was created');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extension runs when making instance
|
||||||
|
final extendedGateway = container.make<PaymentGateway>();
|
||||||
|
extendedGateway.processPayment(199.99);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Example reflector implementation
|
||||||
|
class ExampleReflector implements ReflectorContract {
|
||||||
|
@override
|
||||||
|
String? getName(Symbol symbol) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedClassContract? reflectClass(Type clazz) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedFunctionContract? reflectFunction(Function function) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedInstanceContract? reflectInstance(Object object) => null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract reflectFutureOf(Type type) {
|
||||||
|
throw UnsupportedError('Future reflection not needed for example');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectedTypeContract? reflectType(Type type) => null;
|
||||||
|
}
|
3
packages/container/lib/platform_container.dart
Normal file
3
packages/container/lib/platform_container.dart
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
library platform_container;
|
||||||
|
|
||||||
|
export 'src/container.dart';
|
461
packages/container/lib/src/container.dart
Normal file
461
packages/container/lib/src/container.dart
Normal file
|
@ -0,0 +1,461 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
|
||||||
|
/// Laravel-style container implementation.
|
||||||
|
class IlluminateContainer implements ContainerContract {
|
||||||
|
final ReflectorContract _reflector;
|
||||||
|
final Map<Type, dynamic Function(ContainerContract)> _bindings = {};
|
||||||
|
final Map<Type, dynamic> _instances = {};
|
||||||
|
final Map<String, dynamic> _namedInstances = {};
|
||||||
|
final Map<String, List<Type>> _tags = {};
|
||||||
|
final Map<Type, Map<Type, dynamic>> _contextualBindings = {};
|
||||||
|
final Map<String, Function> _methodBindings = {};
|
||||||
|
final Map<Type, Type> _aliases = {};
|
||||||
|
final Map<Type, List<Function>> _extenders = {};
|
||||||
|
final Map<Type, List<Function>> _reboundCallbacks = {};
|
||||||
|
final Map<Type, dynamic> _scopedInstances = {};
|
||||||
|
final IlluminateContainer? _parent;
|
||||||
|
|
||||||
|
final List<Function> _beforeResolvingCallbacks = [];
|
||||||
|
final List<Function> _resolvingCallbacks = [];
|
||||||
|
final List<Function> _afterResolvingCallbacks = [];
|
||||||
|
|
||||||
|
IlluminateContainer(this._reflector) : _parent = null;
|
||||||
|
|
||||||
|
IlluminateContainer._child(this._parent, this._reflector);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReflectorContract get reflector => _reflector;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isRoot => _parent == null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ContainerContract createChild() {
|
||||||
|
return IlluminateContainer._child(this, _reflector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool bound(String abstract) {
|
||||||
|
return has(Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void bind<T>(T Function(ContainerContract) concrete, {bool shared = false}) {
|
||||||
|
if (shared) {
|
||||||
|
singleton<T>(concrete);
|
||||||
|
} else {
|
||||||
|
registerFactory<T>(concrete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void bindIf<T>(T Function(ContainerContract) concrete,
|
||||||
|
{bool shared = false}) {
|
||||||
|
if (!has<T>()) {
|
||||||
|
bind<T>(concrete, shared: shared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void singleton<T>(T Function(ContainerContract) concrete) {
|
||||||
|
registerLazySingleton<T>(concrete);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void singletonIf<T>(T Function(ContainerContract) concrete) {
|
||||||
|
if (!has<T>()) {
|
||||||
|
singleton<T>(concrete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void scoped<T>(T Function(ContainerContract) concrete) {
|
||||||
|
final type = T;
|
||||||
|
T Function(ContainerContract) wrapper = (container) {
|
||||||
|
if (!_scopedInstances.containsKey(type)) {
|
||||||
|
_scopedInstances[type] = concrete(container);
|
||||||
|
}
|
||||||
|
return _scopedInstances[type] as T;
|
||||||
|
};
|
||||||
|
_bindings[type] = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void scopedIf<T>(T Function(ContainerContract) concrete) {
|
||||||
|
if (!has<T>()) {
|
||||||
|
scoped<T>(concrete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T instance<T>(T instance) {
|
||||||
|
return registerSingleton<T>(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void bindMethod(String method, Function callback) {
|
||||||
|
_methodBindings[method] = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
dynamic call(Function callback, [List<dynamic> parameters = const []]) {
|
||||||
|
final reflected = reflector.reflectFunction(callback);
|
||||||
|
if (reflected == null) {
|
||||||
|
Function.apply(callback, parameters);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final injectedParams = reflected.parameters.map((param) {
|
||||||
|
if (parameters.isNotEmpty) {
|
||||||
|
return parameters.removeAt(0);
|
||||||
|
}
|
||||||
|
return make(param.type.reflectedType);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
final result = Function.apply(callback, injectedParams);
|
||||||
|
return result ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Function wrap(Function callback, [List<dynamic> parameters = const []]) {
|
||||||
|
return () => call(callback, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ContextualBindingBuilder when(Type concrete) {
|
||||||
|
return _ContextualBindingBuilder(this, concrete);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void addContextualBinding(
|
||||||
|
Type concrete, Type abstract, dynamic implementation) {
|
||||||
|
_contextualBindings.putIfAbsent(concrete, () => {})[abstract] =
|
||||||
|
implementation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void beforeResolving<T>(
|
||||||
|
void Function(ContainerContract, T instance) callback) {
|
||||||
|
_beforeResolvingCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void resolving<T>(void Function(ContainerContract, T instance) callback) {
|
||||||
|
_resolvingCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void afterResolving<T>(
|
||||||
|
void Function(ContainerContract, T instance) callback) {
|
||||||
|
_afterResolvingCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool has<T>([Type? t]) {
|
||||||
|
final type = t ?? T;
|
||||||
|
return _bindings.containsKey(type) ||
|
||||||
|
_instances.containsKey(type) ||
|
||||||
|
(_parent?.has<T>(t) ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool hasNamed(String name) {
|
||||||
|
return _namedInstances.containsKey(name) ||
|
||||||
|
(_parent?.hasNamed(name) ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T make<T>([Type? type]) {
|
||||||
|
final resolveType = type ?? T;
|
||||||
|
final concrete = _aliases[resolveType] ?? resolveType;
|
||||||
|
|
||||||
|
// Fire before resolving callbacks
|
||||||
|
_fireBeforeResolvingCallbacks<T>(null);
|
||||||
|
|
||||||
|
// Check for singleton instance
|
||||||
|
if (_instances.containsKey(concrete)) {
|
||||||
|
final instance = _instances[concrete];
|
||||||
|
// Apply extenders to singleton instance
|
||||||
|
final extenders = getExtenders(concrete);
|
||||||
|
for (var extender in extenders) {
|
||||||
|
extender(instance);
|
||||||
|
}
|
||||||
|
_fireResolvingCallbacks<T>(instance as T);
|
||||||
|
return instance as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for contextual binding
|
||||||
|
if (_contextualBindings.containsKey(concrete)) {
|
||||||
|
final bindings = _contextualBindings[concrete]!;
|
||||||
|
if (bindings.containsKey(T)) {
|
||||||
|
final binding = bindings[T];
|
||||||
|
if (binding is Function) {
|
||||||
|
final instance = binding(this) as T;
|
||||||
|
// Apply extenders to contextual binding instance
|
||||||
|
final extenders = getExtenders(concrete);
|
||||||
|
for (var extender in extenders) {
|
||||||
|
extender(instance);
|
||||||
|
}
|
||||||
|
_fireResolvingCallbacks<T>(instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
_fireResolvingCallbacks<T>(binding as T);
|
||||||
|
return binding as T;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for binding
|
||||||
|
if (_bindings.containsKey(concrete)) {
|
||||||
|
final instance = _bindings[concrete]!(this);
|
||||||
|
// Apply extenders to factory instance
|
||||||
|
final extenders = getExtenders(concrete);
|
||||||
|
for (var extender in extenders) {
|
||||||
|
extender(instance);
|
||||||
|
}
|
||||||
|
_fireResolvingCallbacks<T>(instance as T);
|
||||||
|
return instance as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check parent container
|
||||||
|
if (_parent != null && _parent!.has<T>(type)) {
|
||||||
|
return _parent!.make<T>(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to create instance via reflection
|
||||||
|
final reflected = reflector.reflectClass(concrete);
|
||||||
|
if (reflected == null) {
|
||||||
|
throw StateError('Could not reflect type $concrete');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final instance = reflected.newInstance('', []).reflectee as T;
|
||||||
|
// Apply extenders to reflected instance
|
||||||
|
final extenders = getExtenders(concrete);
|
||||||
|
for (var extender in extenders) {
|
||||||
|
extender(instance);
|
||||||
|
}
|
||||||
|
_fireResolvingCallbacks<T>(instance);
|
||||||
|
return instance;
|
||||||
|
} catch (e) {
|
||||||
|
throw StateError(
|
||||||
|
'Failed to create instance of $concrete: ${e.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fireBeforeResolvingCallbacks<T>(T? instance) {
|
||||||
|
for (var callback in _beforeResolvingCallbacks) {
|
||||||
|
callback(this, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _fireResolvingCallbacks<T>(T instance) {
|
||||||
|
for (var callback in _resolvingCallbacks) {
|
||||||
|
callback(this, instance);
|
||||||
|
}
|
||||||
|
for (var callback in _afterResolvingCallbacks) {
|
||||||
|
callback(this, instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<T> makeAsync<T>([Type? type]) async {
|
||||||
|
try {
|
||||||
|
final instance = make<T>(type);
|
||||||
|
if (instance is Future<T>) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
return Future<T>.value(instance);
|
||||||
|
} catch (e) {
|
||||||
|
final futureType = reflector.reflectFutureOf(type ?? T);
|
||||||
|
final instance = futureType.newInstance('', []);
|
||||||
|
if (instance.reflectee is Future<T>) {
|
||||||
|
return instance.reflectee as Future<T>;
|
||||||
|
}
|
||||||
|
throw StateError('Failed to create Future<$T>: Invalid instance type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T registerSingleton<T>(T object, {Type? as}) {
|
||||||
|
final type = as ?? T;
|
||||||
|
if (_instances.containsKey(type)) {
|
||||||
|
throw StateError('Singleton already registered for type $type');
|
||||||
|
}
|
||||||
|
_instances[type] = object;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T Function(ContainerContract) registerFactory<T>(
|
||||||
|
T Function(ContainerContract) factory,
|
||||||
|
{Type? as}) {
|
||||||
|
final type = as ?? T;
|
||||||
|
_bindings[type] = factory;
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T Function(ContainerContract) registerLazySingleton<T>(
|
||||||
|
T Function(ContainerContract) factory,
|
||||||
|
{Type? as}) {
|
||||||
|
final type = as ?? T;
|
||||||
|
T Function(ContainerContract) wrapper = (container) {
|
||||||
|
if (!_instances.containsKey(type)) {
|
||||||
|
_instances[type] = factory(container);
|
||||||
|
}
|
||||||
|
return _instances[type] as T;
|
||||||
|
};
|
||||||
|
_bindings[type] = wrapper;
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T findByName<T>(String name) {
|
||||||
|
if (_namedInstances.containsKey(name)) {
|
||||||
|
return _namedInstances[name] as T;
|
||||||
|
}
|
||||||
|
if (_parent != null) {
|
||||||
|
return _parent!.findByName<T>(name);
|
||||||
|
}
|
||||||
|
throw StateError('No singleton registered with name "$name"');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
T registerNamedSingleton<T>(String name, T object) {
|
||||||
|
if (_namedInstances.containsKey(name)) {
|
||||||
|
throw StateError('Singleton already registered with name "$name"');
|
||||||
|
}
|
||||||
|
_namedInstances[name] = object;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void tag(List<Type> abstracts, String tag) {
|
||||||
|
_tags.putIfAbsent(tag, () => []).addAll(abstracts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<T> tagged<T>(String tag) {
|
||||||
|
final types = _tags[tag] ?? [];
|
||||||
|
if (types.isEmpty) {
|
||||||
|
throw StateError('No types registered for tag "$tag"');
|
||||||
|
}
|
||||||
|
|
||||||
|
final instances = <T>[];
|
||||||
|
for (final type in types) {
|
||||||
|
if (_bindings.containsKey(type)) {
|
||||||
|
final instance = _bindings[type]!(this) as T;
|
||||||
|
instances.add(instance);
|
||||||
|
} else if (_parent != null && _parent!.has(type)) {
|
||||||
|
final instance = _parent!.make(type) as T;
|
||||||
|
instances.add(instance);
|
||||||
|
} else {
|
||||||
|
throw StateError('Could not resolve type $type');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void alias(Type abstract, Type alias) {
|
||||||
|
if (abstract == alias) {
|
||||||
|
throw StateError('$abstract is aliased to itself.');
|
||||||
|
}
|
||||||
|
_aliases[alias] = abstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAlias(String name) {
|
||||||
|
return _aliases.keys.any((type) => type.toString() == name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type getAlias(Type abstract) {
|
||||||
|
return _aliases[abstract] ?? abstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void extend(Type abstract, Function(dynamic instance) extension) {
|
||||||
|
_extenders.putIfAbsent(abstract, () => []).add(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Function> getExtenders(Type abstract) {
|
||||||
|
return _extenders[abstract] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forgetExtenders(Type abstract) {
|
||||||
|
_extenders.remove(abstract);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forgetInstance(Type abstract) {
|
||||||
|
_instances.remove(abstract);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forgetInstances() {
|
||||||
|
_instances.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void forgetScopedInstances() {
|
||||||
|
_scopedInstances.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void flush() {
|
||||||
|
_bindings.clear();
|
||||||
|
_instances.clear();
|
||||||
|
_namedInstances.clear();
|
||||||
|
_tags.clear();
|
||||||
|
_contextualBindings.clear();
|
||||||
|
_methodBindings.clear();
|
||||||
|
_aliases.clear();
|
||||||
|
_extenders.clear();
|
||||||
|
_reboundCallbacks.clear();
|
||||||
|
_scopedInstances.clear();
|
||||||
|
_beforeResolvingCallbacks.clear();
|
||||||
|
_resolvingCallbacks.clear();
|
||||||
|
_afterResolvingCallbacks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void rebinding(Type abstract, Function(ContainerContract, dynamic) callback) {
|
||||||
|
_reboundCallbacks.putIfAbsent(abstract, () => []).add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void refresh(Type abstract, dynamic target, String method) {
|
||||||
|
final instance = make(abstract);
|
||||||
|
|
||||||
|
for (var callback in _reboundCallbacks[abstract] ?? []) {
|
||||||
|
callback(this, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
Function.apply(target[method], [instance]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ContextualBindingBuilder implements ContextualBindingBuilder {
|
||||||
|
final IlluminateContainer _container;
|
||||||
|
final Type _concrete;
|
||||||
|
Type? _needsType;
|
||||||
|
|
||||||
|
_ContextualBindingBuilder(this._container, this._concrete);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ContextualBindingBuilder needs<T>() {
|
||||||
|
_needsType = T;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void give(dynamic implementation) {
|
||||||
|
if (_needsType == null) {
|
||||||
|
throw StateError('Must call needs() before give()');
|
||||||
|
}
|
||||||
|
_container.addContextualBinding(_concrete, _needsType!, implementation);
|
||||||
|
}
|
||||||
|
}
|
561
packages/container/pubspec.lock
Normal file
561
packages/container/pubspec.lock
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
# Generated by pub
|
||||||
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "73.0.0"
|
||||||
|
_macros:
|
||||||
|
dependency: transitive
|
||||||
|
description: dart
|
||||||
|
source: sdk
|
||||||
|
version: "0.3.2"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.8.0"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.6.0"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.12.0"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
build:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build
|
||||||
|
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
build_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_config
|
||||||
|
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
build_daemon:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_daemon
|
||||||
|
sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
|
build_resolvers:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_resolvers
|
||||||
|
sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
build_runner:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: build_runner
|
||||||
|
sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.13"
|
||||||
|
build_runner_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: build_runner_core
|
||||||
|
sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.3.2"
|
||||||
|
built_collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: built_collection
|
||||||
|
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.1"
|
||||||
|
built_value:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: built_value
|
||||||
|
sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.9.2"
|
||||||
|
checked_yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: checked_yaml
|
||||||
|
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
code_builder:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: code_builder
|
||||||
|
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.10.1"
|
||||||
|
collection:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.19.1"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
|
coverage:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: coverage
|
||||||
|
sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.11.0"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.6"
|
||||||
|
dart_style:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dart_style
|
||||||
|
sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.7"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
graphs:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: graphs
|
||||||
|
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
http_multi_server:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_multi_server
|
||||||
|
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "76d306a1c3afb33fe82e2bbacad62a61f409b5634c915fceb0d799de1a913360"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.1"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.1"
|
||||||
|
json_annotation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: json_annotation
|
||||||
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.9.0"
|
||||||
|
lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
macros:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: macros
|
||||||
|
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2-main.4"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.16+1"
|
||||||
|
meta:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.16.0"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
mockito:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: mockito
|
||||||
|
sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.4"
|
||||||
|
node_preamble:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_preamble
|
||||||
|
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.9.1"
|
||||||
|
platform_contracts:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "../contracts"
|
||||||
|
relative: true
|
||||||
|
source: path
|
||||||
|
version: "1.0.0"
|
||||||
|
pool:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pool
|
||||||
|
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.1"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.4"
|
||||||
|
pubspec_parse:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pubspec_parse
|
||||||
|
sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
shelf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf
|
||||||
|
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.2"
|
||||||
|
shelf_packages_handler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_packages_handler
|
||||||
|
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
shelf_static:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_static
|
||||||
|
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.3"
|
||||||
|
shelf_web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_web_socket
|
||||||
|
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
source_gen:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_gen
|
||||||
|
sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.0"
|
||||||
|
source_map_stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_map_stack_trace
|
||||||
|
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
source_maps:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_maps
|
||||||
|
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.12"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.12.0"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
stream_transform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_transform
|
||||||
|
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: test
|
||||||
|
sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.25.8"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.3"
|
||||||
|
test_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_core
|
||||||
|
sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.5"
|
||||||
|
timing:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: timing
|
||||||
|
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
|
vm_service:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vm_service
|
||||||
|
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "14.3.1"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket
|
||||||
|
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
webkit_inspection_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webkit_inspection_protocol
|
||||||
|
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.1"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
|
sdks:
|
||||||
|
dart: ">=3.5.0 <4.0.0"
|
19
packages/container/pubspec.yaml
Normal file
19
packages/container/pubspec.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
name: platform_container
|
||||||
|
description: Laravel-style container implementation for the Protevus Platform
|
||||||
|
version: 0.1.0
|
||||||
|
publish_to: none
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
platform_contracts:
|
||||||
|
path: ../contracts
|
||||||
|
meta: ^1.9.0
|
||||||
|
collection: ^1.17.0
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
test: ^1.24.0
|
||||||
|
mockito: ^5.4.0
|
||||||
|
build_runner: ^2.4.0
|
||||||
|
lints: ^2.1.0
|
257
packages/container/test/Container/container_test.dart
Normal file
257
packages/container/test/Container/container_test.dart
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:mockito/annotations.dart';
|
||||||
|
|
||||||
|
import '../laravel_container_test.mocks.dart';
|
||||||
|
import '../stubs.dart';
|
||||||
|
|
||||||
|
@GenerateMocks([
|
||||||
|
ReflectorContract,
|
||||||
|
ReflectedClassContract,
|
||||||
|
ReflectedInstanceContract,
|
||||||
|
ReflectedFunctionContract,
|
||||||
|
ReflectedParameterContract,
|
||||||
|
ReflectedTypeContract
|
||||||
|
])
|
||||||
|
void main() {
|
||||||
|
late IlluminateContainer container;
|
||||||
|
late MockReflectorContract reflector;
|
||||||
|
late MockReflectedClassContract reflectedClass;
|
||||||
|
late MockReflectedInstanceContract reflectedInstance;
|
||||||
|
late MockReflectedFunctionContract reflectedFunction;
|
||||||
|
late MockReflectedParameterContract reflectedParameter;
|
||||||
|
late MockReflectedTypeContract reflectedType;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
reflector = MockReflectorContract();
|
||||||
|
reflectedClass = MockReflectedClassContract();
|
||||||
|
reflectedInstance = MockReflectedInstanceContract();
|
||||||
|
reflectedFunction = MockReflectedFunctionContract();
|
||||||
|
reflectedParameter = MockReflectedParameterContract();
|
||||||
|
reflectedType = MockReflectedTypeContract();
|
||||||
|
container = IlluminateContainer(reflector);
|
||||||
|
|
||||||
|
// Setup default reflection behavior
|
||||||
|
when(reflector.reflectClass(any)).thenReturn(reflectedClass);
|
||||||
|
when(reflectedClass.newInstance('', [])).thenReturn(reflectedInstance);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container Basic Resolution', () {
|
||||||
|
test('testClosureResolution', () {
|
||||||
|
container.bind<String>((c) => 'Taylor');
|
||||||
|
expect(container.make<String>(), equals('Taylor'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testBindIfDoesntRegisterIfServiceAlreadyRegistered', () {
|
||||||
|
container.bind<String>((c) => 'Taylor');
|
||||||
|
container.bindIf<String>((c) => 'Dayle');
|
||||||
|
expect(container.make<String>(), equals('Taylor'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testBindIfDoesRegisterIfServiceNotRegisteredYet', () {
|
||||||
|
container.bindIf<String>((c) => 'Dayle');
|
||||||
|
expect(container.make<String>(), equals('Dayle'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testAutoConcreteResolution', () {
|
||||||
|
final instance = ContainerConcreteStub();
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(instance);
|
||||||
|
expect(container.make<ContainerConcreteStub>(),
|
||||||
|
isA<ContainerConcreteStub>());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container Singleton', () {
|
||||||
|
test('testSharedClosureResolution', () {
|
||||||
|
container
|
||||||
|
.singleton<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testSingletonIfDoesntRegisterIfBindingAlreadyRegistered', () {
|
||||||
|
container
|
||||||
|
.singleton<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
container
|
||||||
|
.singletonIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testSingletonIfDoesRegisterIfBindingNotRegisteredYet', () {
|
||||||
|
container
|
||||||
|
.singletonIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testBindingAnInstanceAsShared', () {
|
||||||
|
final instance = ContainerConcreteStub();
|
||||||
|
container.instance<ContainerConcreteStub>(instance);
|
||||||
|
expect(
|
||||||
|
identical(container.make<ContainerConcreteStub>(), instance), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container Scoped', () {
|
||||||
|
test('testScopedClosureResolution', () {
|
||||||
|
container.scoped<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
|
||||||
|
container.forgetScopedInstances();
|
||||||
|
final third = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(second, third), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testScopedIfDoesntRegisterIfBindingAlreadyRegistered', () {
|
||||||
|
container.scoped<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
container.scopedIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testScopedIfDoesRegisterIfBindingNotRegisteredYet', () {
|
||||||
|
container.scopedIf<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
final first = container.make<ContainerConcreteStub>();
|
||||||
|
final second = container.make<ContainerConcreteStub>();
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container Dependencies', () {
|
||||||
|
test('testAbstractToConcreteResolution', () {
|
||||||
|
final impl = ContainerImplementationStub();
|
||||||
|
final dependent = ContainerDependentStub(impl);
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(dependent);
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
|
||||||
|
final instance = container.make<ContainerDependentStub>();
|
||||||
|
expect(instance.impl, isA<ContainerImplementationStub>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testNestedDependencyResolution', () {
|
||||||
|
final impl = ContainerImplementationStub();
|
||||||
|
final dependent = ContainerDependentStub(impl);
|
||||||
|
final nested = ContainerNestedDependentStub(dependent);
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(nested);
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
|
||||||
|
final instance = container.make<ContainerNestedDependentStub>();
|
||||||
|
expect(instance.inner, isA<ContainerDependentStub>());
|
||||||
|
expect(instance.inner.impl, isA<ContainerImplementationStub>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testContainerIsPassedToResolvers', () {
|
||||||
|
container.bind<ContainerContract>((c) => c);
|
||||||
|
final resolved = container.make<ContainerContract>();
|
||||||
|
expect(identical(resolved, container), isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container Aliases', () {
|
||||||
|
test('testAliases', () {
|
||||||
|
final impl = ContainerImplementationStub('bar');
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(impl);
|
||||||
|
|
||||||
|
container.bind<IContainerContractStub>((c) => impl);
|
||||||
|
container.alias(IContainerContractStub, ContainerImplementationStub);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.make<IContainerContractStub>().getValue(), equals('bar'));
|
||||||
|
expect(container.make<ContainerImplementationStub>().getValue(),
|
||||||
|
equals('bar'));
|
||||||
|
expect(container.isAlias('ContainerImplementationStub'), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testAliasesWithArrayOfParameters', () {
|
||||||
|
final impl = ContainerImplementationStub('foo');
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(impl);
|
||||||
|
|
||||||
|
container.bind<IContainerContractStub>((c) => impl);
|
||||||
|
container.alias(IContainerContractStub, ContainerImplementationStub);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.make<IContainerContractStub>().getValue(), equals('foo'));
|
||||||
|
expect(container.make<ContainerImplementationStub>().getValue(),
|
||||||
|
equals('foo'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testGetAliasRecursive', () {
|
||||||
|
final impl = ContainerImplementationStub('foo');
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(impl);
|
||||||
|
|
||||||
|
// Bind the implementation to the interface
|
||||||
|
container.bind<IContainerContractStub>((c) => impl);
|
||||||
|
|
||||||
|
// Create alias chain in reverse order
|
||||||
|
container.alias(ContainerImplementationStub, StubAlias);
|
||||||
|
container.alias(IContainerContractStub, ContainerImplementationStub);
|
||||||
|
|
||||||
|
// Verify immediate aliases
|
||||||
|
expect(
|
||||||
|
container.getAlias(StubAlias), equals(ContainerImplementationStub));
|
||||||
|
expect(container.getAlias(ContainerImplementationStub),
|
||||||
|
equals(IContainerContractStub));
|
||||||
|
|
||||||
|
// Verify instance resolution through alias chain
|
||||||
|
final instance = container.make<IContainerContractStub>();
|
||||||
|
expect(instance.getValue(), equals('foo'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container State', () {
|
||||||
|
test('testBindingsCanBeOverridden', () {
|
||||||
|
container.bind<String>((c) => 'bar');
|
||||||
|
container.bind<String>((c) => 'baz');
|
||||||
|
expect(container.make<String>(), equals('baz'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testContainerFlushFlushesAllBindingsAliasesAndResolvedInstances', () {
|
||||||
|
container
|
||||||
|
.bind<IContainerContractStub>((c) => ContainerImplementationStub());
|
||||||
|
container.bind<ContainerConcreteStub>((c) => ContainerConcreteStub());
|
||||||
|
container.tag([ContainerConcreteStub], 'services');
|
||||||
|
container.alias(IContainerContractStub, ContainerImplementationStub);
|
||||||
|
|
||||||
|
expect(container.has<IContainerContractStub>(), isTrue);
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isTrue);
|
||||||
|
expect(container.isAlias('ContainerImplementationStub'), isTrue);
|
||||||
|
|
||||||
|
container.flush();
|
||||||
|
|
||||||
|
expect(container.has<IContainerContractStub>(), isFalse);
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isFalse);
|
||||||
|
expect(container.isAlias('ContainerImplementationStub'), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testForgetInstanceForgetsInstance', () {
|
||||||
|
final instance = ContainerConcreteStub();
|
||||||
|
container.instance<ContainerConcreteStub>(instance);
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isTrue);
|
||||||
|
container.forgetInstance(ContainerConcreteStub);
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('testForgetInstancesForgetsAllInstances', () {
|
||||||
|
final instance1 = ContainerConcreteStub();
|
||||||
|
final instance2 = ContainerImplementationStub();
|
||||||
|
container.instance<ContainerConcreteStub>(instance1);
|
||||||
|
container.instance<ContainerImplementationStub>(instance2);
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isTrue);
|
||||||
|
expect(container.has<ContainerImplementationStub>(), isTrue);
|
||||||
|
container.forgetInstances();
|
||||||
|
expect(container.has<ContainerConcreteStub>(), isFalse);
|
||||||
|
expect(container.has<ContainerImplementationStub>(), isFalse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
126
packages/container/test/container_test.dart
Normal file
126
packages/container/test/container_test.dart
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:mockito/annotations.dart';
|
||||||
|
|
||||||
|
import 'container_test.mocks.dart';
|
||||||
|
|
||||||
|
@GenerateMocks(
|
||||||
|
[ReflectorContract, ReflectedTypeContract, ReflectedInstanceContract])
|
||||||
|
void main() {
|
||||||
|
late IlluminateContainer container;
|
||||||
|
late MockReflectorContract reflector;
|
||||||
|
late MockReflectedTypeContract reflectedType;
|
||||||
|
late MockReflectedInstanceContract reflectedInstance;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
reflector = MockReflectorContract();
|
||||||
|
reflectedType = MockReflectedTypeContract();
|
||||||
|
reflectedInstance = MockReflectedInstanceContract();
|
||||||
|
container = IlluminateContainer(reflector);
|
||||||
|
|
||||||
|
// Setup default reflection behavior
|
||||||
|
when(reflector.reflectClass(any)).thenReturn(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Container', () {
|
||||||
|
test('isRoot returns true for root container', () {
|
||||||
|
expect(container.isRoot, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('isRoot returns false for child container', () {
|
||||||
|
final child = container.createChild();
|
||||||
|
expect(child.isRoot, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('has returns true for registered singleton', () {
|
||||||
|
container.registerSingleton<String>('test');
|
||||||
|
expect(container.has<String>(), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('has returns true for registered factory', () {
|
||||||
|
container.registerFactory<String>((c) => 'test');
|
||||||
|
expect(container.has<String>(), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('has returns true for registered lazy singleton', () {
|
||||||
|
container.registerLazySingleton<String>((c) => 'test');
|
||||||
|
expect(container.has<String>(), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('hasNamed returns true for registered named singleton', () {
|
||||||
|
container.registerNamedSingleton<String>('test.name', 'test');
|
||||||
|
expect(container.hasNamed('test.name'), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('make returns singleton instance', () {
|
||||||
|
container.registerSingleton<String>('test');
|
||||||
|
expect(container.make<String>(), equals('test'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('make creates new instance for factory', () {
|
||||||
|
var count = 0;
|
||||||
|
container.registerFactory<String>((c) => 'test${count++}');
|
||||||
|
expect(container.make<String>(), equals('test0'));
|
||||||
|
expect(container.make<String>(), equals('test1'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('make returns same instance for lazy singleton', () {
|
||||||
|
var count = 0;
|
||||||
|
container.registerLazySingleton<String>((c) => 'test${count++}');
|
||||||
|
expect(container.make<String>(), equals('test0'));
|
||||||
|
expect(container.make<String>(), equals('test0'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('makeAsync returns Future for async dependency', () async {
|
||||||
|
// Setup mock behavior
|
||||||
|
when(reflector.reflectFutureOf(String)).thenReturn(reflectedType);
|
||||||
|
when(reflectedType.newInstance('', [])).thenReturn(reflectedInstance);
|
||||||
|
when(reflectedInstance.reflectee).thenAnswer((_) => Future.value('test'));
|
||||||
|
|
||||||
|
final result = await container.makeAsync<String>();
|
||||||
|
expect(result, equals('test'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('findByName returns named singleton', () {
|
||||||
|
container.registerNamedSingleton<String>('test.name', 'test');
|
||||||
|
expect(container.findByName<String>('test.name'), equals('test'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('child container inherits parent bindings', () {
|
||||||
|
container.registerSingleton<String>('test');
|
||||||
|
final child = container.createChild();
|
||||||
|
expect(child.make<String>(), equals('test'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('child container can override parent bindings', () {
|
||||||
|
container.registerSingleton<String>('parent');
|
||||||
|
final child = container.createChild() as IlluminateContainer;
|
||||||
|
child.registerSingleton<String>('child');
|
||||||
|
expect(child.make<String>(), equals('child'));
|
||||||
|
expect(container.make<String>(), equals('parent'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when making unregistered type without reflection', () {
|
||||||
|
expect(() => container.make<String>(), throwsStateError);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when making named singleton that does not exist', () {
|
||||||
|
expect(() => container.findByName<String>('missing'), throwsStateError);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when registering duplicate singleton', () {
|
||||||
|
container.registerSingleton<String>('test');
|
||||||
|
expect(
|
||||||
|
() => container.registerSingleton<String>('test2'), throwsStateError);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws when registering duplicate named singleton', () {
|
||||||
|
container.registerNamedSingleton<String>('test.name', 'test');
|
||||||
|
expect(
|
||||||
|
() => container.registerNamedSingleton<String>('test.name', 'test2'),
|
||||||
|
throwsStateError);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
241
packages/container/test/container_test.mocks.dart
Normal file
241
packages/container/test/container_test.mocks.dart
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
// Mocks generated by Mockito 5.4.4 from annotations
|
||||||
|
// in platform_illuminate_container/test/container_test.dart.
|
||||||
|
// Do not manually edit this file.
|
||||||
|
|
||||||
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
|
import 'package:mockito/mockito.dart' as _i1;
|
||||||
|
import 'package:mockito/src/dummies.dart' as _i3;
|
||||||
|
import 'package:platform_contracts/src/reflection/reflector_contract.dart'
|
||||||
|
as _i2;
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: avoid_redundant_argument_values
|
||||||
|
// ignore_for_file: avoid_setters_without_getters
|
||||||
|
// ignore_for_file: comment_references
|
||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package
|
||||||
|
// ignore_for_file: implementation_imports
|
||||||
|
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||||
|
// ignore_for_file: prefer_const_constructors
|
||||||
|
// ignore_for_file: unnecessary_parenthesis
|
||||||
|
// ignore_for_file: camel_case_types
|
||||||
|
// ignore_for_file: subtype_of_sealed_class
|
||||||
|
|
||||||
|
class _FakeReflectedTypeContract_0 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedTypeContract {
|
||||||
|
_FakeReflectedTypeContract_0(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeType_1 extends _i1.SmartFake implements Type {
|
||||||
|
_FakeType_1(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeReflectedInstanceContract_2 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedInstanceContract {
|
||||||
|
_FakeReflectedInstanceContract_2(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeReflectedClassContract_3 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedClassContract {
|
||||||
|
_FakeReflectedClassContract_3(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectorContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectorContract extends _i1.Mock implements _i2.ReflectorContract {
|
||||||
|
MockReflectorContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? getName(Symbol? symbol) => (super.noSuchMethod(Invocation.method(
|
||||||
|
#getName,
|
||||||
|
[symbol],
|
||||||
|
)) as String?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedClassContract? reflectClass(Type? clazz) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectClass,
|
||||||
|
[clazz],
|
||||||
|
)) as _i2.ReflectedClassContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedFunctionContract? reflectFunction(Function? function) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectFunction,
|
||||||
|
[function],
|
||||||
|
)) as _i2.ReflectedFunctionContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract? reflectType(Type? type) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectType,
|
||||||
|
[type],
|
||||||
|
)) as _i2.ReflectedTypeContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract? reflectInstance(Object? object) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectInstance,
|
||||||
|
[object],
|
||||||
|
)) as _i2.ReflectedInstanceContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract reflectFutureOf(Type? type) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#reflectFutureOf,
|
||||||
|
[type],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedTypeContract_0(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#reflectFutureOf,
|
||||||
|
[type],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedTypeContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedTypeContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedTypeContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedTypeContract {
|
||||||
|
MockReflectedTypeContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#name),
|
||||||
|
returnValue: _i3.dummyValue<String>(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#name),
|
||||||
|
),
|
||||||
|
) as String);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#typeParameters),
|
||||||
|
returnValue: <_i2.ReflectedTypeParameterContract>[],
|
||||||
|
) as List<_i2.ReflectedTypeParameterContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type get reflectedType => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
returnValue: _FakeType_1(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
),
|
||||||
|
) as Type);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#isAssignableTo,
|
||||||
|
[other],
|
||||||
|
),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract newInstance(
|
||||||
|
String? constructorName,
|
||||||
|
List<dynamic>? positionalArguments, [
|
||||||
|
Map<String, dynamic>? namedArguments = const {},
|
||||||
|
List<Type>? typeArguments = const [],
|
||||||
|
]) =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedInstanceContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedInstanceContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedInstanceContract {
|
||||||
|
MockReflectedInstanceContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#type),
|
||||||
|
returnValue: _FakeReflectedTypeContract_0(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#type),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedTypeContract);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedClassContract get clazz => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#clazz),
|
||||||
|
returnValue: _FakeReflectedClassContract_3(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#clazz),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedClassContract);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract getField(String? name) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#getField,
|
||||||
|
[name],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#getField,
|
||||||
|
[name],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
293
packages/container/test/laravel_container_test.dart
Normal file
293
packages/container/test/laravel_container_test.dart
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
import 'package:platform_contracts/contracts.dart';
|
||||||
|
import 'package:platform_container/platform_container.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:mockito/annotations.dart';
|
||||||
|
|
||||||
|
import 'laravel_container_test.mocks.dart';
|
||||||
|
|
||||||
|
// Test classes
|
||||||
|
abstract class PaymentGateway {}
|
||||||
|
|
||||||
|
class StripeGateway implements PaymentGateway {}
|
||||||
|
|
||||||
|
class PayPalGateway implements PaymentGateway {}
|
||||||
|
|
||||||
|
class Service {}
|
||||||
|
|
||||||
|
class SpecialService extends Service {}
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
final Service service;
|
||||||
|
Client(this.service);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GenerateMocks([
|
||||||
|
ReflectorContract,
|
||||||
|
ReflectedClassContract,
|
||||||
|
ReflectedInstanceContract,
|
||||||
|
ReflectedFunctionContract,
|
||||||
|
ReflectedParameterContract,
|
||||||
|
ReflectedTypeContract
|
||||||
|
])
|
||||||
|
void main() {
|
||||||
|
late IlluminateContainer container;
|
||||||
|
late MockReflectorContract reflector;
|
||||||
|
late MockReflectedClassContract reflectedClass;
|
||||||
|
late MockReflectedInstanceContract reflectedInstance;
|
||||||
|
late MockReflectedFunctionContract reflectedFunction;
|
||||||
|
late MockReflectedParameterContract reflectedParameter;
|
||||||
|
late MockReflectedTypeContract reflectedType;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
reflector = MockReflectorContract();
|
||||||
|
reflectedClass = MockReflectedClassContract();
|
||||||
|
reflectedInstance = MockReflectedInstanceContract();
|
||||||
|
reflectedFunction = MockReflectedFunctionContract();
|
||||||
|
reflectedParameter = MockReflectedParameterContract();
|
||||||
|
reflectedType = MockReflectedTypeContract();
|
||||||
|
container = IlluminateContainer(reflector);
|
||||||
|
|
||||||
|
// Setup default reflection behavior
|
||||||
|
when(reflector.reflectClass(any)).thenReturn(null);
|
||||||
|
when(reflector.reflectFunction(any)).thenReturn(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Laravel Container', () {
|
||||||
|
test('contextual binding with when/needs/give', () {
|
||||||
|
// When we set up a contextual binding
|
||||||
|
container.when(Client).needs<Service>().give(SpecialService());
|
||||||
|
|
||||||
|
// Then the contextual binding should be used
|
||||||
|
when(reflector.reflectClass(Client)).thenReturn(reflectedClass);
|
||||||
|
when(reflectedClass.newInstance('', [])).thenReturn(reflectedInstance);
|
||||||
|
when(reflectedInstance.reflectee).thenReturn(Client(SpecialService()));
|
||||||
|
|
||||||
|
final client = container.make<Client>();
|
||||||
|
expect(client.service, isA<SpecialService>());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('method injection with call', () {
|
||||||
|
void method(Service service) {}
|
||||||
|
|
||||||
|
// Setup reflection mocks
|
||||||
|
when(reflector.reflectFunction(method)).thenReturn(reflectedFunction);
|
||||||
|
when(reflectedFunction.parameters).thenReturn([reflectedParameter]);
|
||||||
|
when(reflectedParameter.type).thenReturn(reflectedType);
|
||||||
|
when(reflectedType.reflectedType).thenReturn(Service);
|
||||||
|
|
||||||
|
// Register service
|
||||||
|
final service = Service();
|
||||||
|
container.registerSingleton(service);
|
||||||
|
|
||||||
|
// When we call the method through the container
|
||||||
|
container.call(method);
|
||||||
|
|
||||||
|
// Then dependencies should be injected
|
||||||
|
verify(reflector.reflectFunction(method)).called(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('resolution hooks', () {
|
||||||
|
// Given some resolution hooks
|
||||||
|
final resolving = <String>[];
|
||||||
|
final testValue = 'test';
|
||||||
|
|
||||||
|
// Register hooks with explicit type parameters
|
||||||
|
void beforeCallback(ContainerContract c, String? i) =>
|
||||||
|
resolving.add('before');
|
||||||
|
void resolvingCallback(ContainerContract c, String i) =>
|
||||||
|
resolving.add('resolving');
|
||||||
|
void afterCallback(ContainerContract c, String i) =>
|
||||||
|
resolving.add('after');
|
||||||
|
|
||||||
|
container.beforeResolving<String>(beforeCallback);
|
||||||
|
container.resolving<String>(resolvingCallback);
|
||||||
|
container.afterResolving<String>(afterCallback);
|
||||||
|
|
||||||
|
// Register a value to resolve
|
||||||
|
container.registerSingleton<String>(testValue);
|
||||||
|
|
||||||
|
// When we resolve a type
|
||||||
|
container.make<String>();
|
||||||
|
|
||||||
|
// Then hooks should be called in order
|
||||||
|
expect(resolving, equals(['before', 'resolving', 'after']));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('method binding', () {
|
||||||
|
// Setup reflection mocks
|
||||||
|
when(reflector.reflectFunction(any)).thenReturn(reflectedFunction);
|
||||||
|
when(reflectedFunction.parameters).thenReturn([]);
|
||||||
|
|
||||||
|
// Register a method
|
||||||
|
String boundMethod() => 'bound';
|
||||||
|
container.bindMethod('test', boundMethod);
|
||||||
|
|
||||||
|
// Call a test method
|
||||||
|
String testMethod() => 'test';
|
||||||
|
final result = container.call(testMethod);
|
||||||
|
|
||||||
|
// Verify the method was called
|
||||||
|
verify(reflector.reflectFunction(any)).called(1);
|
||||||
|
expect(result, equals('test'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('tagged bindings', () {
|
||||||
|
// Create gateway instances
|
||||||
|
final stripeGateway = StripeGateway();
|
||||||
|
final paypalGateway = PayPalGateway();
|
||||||
|
|
||||||
|
// Register factories for concrete types
|
||||||
|
container.registerFactory<StripeGateway>((c) => stripeGateway);
|
||||||
|
container.registerFactory<PayPalGateway>((c) => paypalGateway);
|
||||||
|
|
||||||
|
// Register types in order
|
||||||
|
container.tag([StripeGateway, PayPalGateway], 'gateways');
|
||||||
|
|
||||||
|
// When we resolve tagged bindings
|
||||||
|
final gateways = container.tagged<PaymentGateway>('gateways');
|
||||||
|
|
||||||
|
// Then all tagged instances should be returned in order
|
||||||
|
expect(gateways.length, equals(2));
|
||||||
|
expect(gateways[0], same(stripeGateway));
|
||||||
|
expect(gateways[1], same(paypalGateway));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shared bindings', () {
|
||||||
|
// Given a shared binding
|
||||||
|
container.bind<String>((c) => 'test', shared: true);
|
||||||
|
|
||||||
|
// When we resolve multiple times
|
||||||
|
final first = container.make<String>();
|
||||||
|
final second = container.make<String>();
|
||||||
|
|
||||||
|
// Then the same instance should be returned
|
||||||
|
expect(identical(first, second), isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('child container inherits bindings', () {
|
||||||
|
// Given a parent binding
|
||||||
|
container.bind<String>((c) => 'parent');
|
||||||
|
|
||||||
|
// When we create a child container
|
||||||
|
final child = container.createChild();
|
||||||
|
|
||||||
|
// Then the child should inherit bindings
|
||||||
|
expect(child.make<String>(), equals('parent'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('child container can override bindings', () {
|
||||||
|
// Given a parent binding
|
||||||
|
container.registerFactory<String>((c) => 'parent');
|
||||||
|
|
||||||
|
// When we override in child
|
||||||
|
final child = container.createChild();
|
||||||
|
child.registerFactory<String>((c) => 'child');
|
||||||
|
|
||||||
|
// Then child should use its own binding
|
||||||
|
expect(child.make<String>(), equals('child'));
|
||||||
|
expect(container.make<String>(), equals('parent'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('scoped bindings', () {
|
||||||
|
// Given a scoped binding
|
||||||
|
var counter = 0;
|
||||||
|
container.scoped<String>((c) => 'scoped${counter++}');
|
||||||
|
|
||||||
|
// When we resolve multiple times
|
||||||
|
final first = container.make<String>();
|
||||||
|
final second = container.make<String>();
|
||||||
|
|
||||||
|
// Then the same instance should be returned
|
||||||
|
expect(first, equals(second));
|
||||||
|
|
||||||
|
// When we forget scoped instances
|
||||||
|
container.forgetScopedInstances();
|
||||||
|
|
||||||
|
// Then a new instance should be created
|
||||||
|
final third = container.make<String>();
|
||||||
|
expect(third, isNot(equals(second)));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('type aliases', () {
|
||||||
|
// Given a binding and an alias
|
||||||
|
container.bind<PaymentGateway>((c) => StripeGateway());
|
||||||
|
container.alias(PaymentGateway, StripeGateway);
|
||||||
|
|
||||||
|
// When we check if it's an alias
|
||||||
|
final isAlias = container.isAlias('StripeGateway');
|
||||||
|
|
||||||
|
// Then it should be true
|
||||||
|
expect(isAlias, isTrue);
|
||||||
|
|
||||||
|
// And the alias should resolve to the original type
|
||||||
|
expect(container.getAlias(StripeGateway), equals(PaymentGateway));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extending instances', () {
|
||||||
|
print('Starting extending instances test');
|
||||||
|
|
||||||
|
// Given a binding and an extender
|
||||||
|
var extended = false;
|
||||||
|
print('Setting up binding and extender');
|
||||||
|
container.bind<Service>((c) => Service());
|
||||||
|
container.extend(Service, (instance) {
|
||||||
|
print('Extender called');
|
||||||
|
extended = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
print('Making instance');
|
||||||
|
// When we make an instance
|
||||||
|
container.make<Service>();
|
||||||
|
|
||||||
|
print('Extended value: $extended');
|
||||||
|
// Then the extender should be called
|
||||||
|
expect(extended, isTrue);
|
||||||
|
|
||||||
|
// And we can get the extenders
|
||||||
|
expect(container.getExtenders(Service).length, equals(1));
|
||||||
|
|
||||||
|
// And we can forget them
|
||||||
|
container.forgetExtenders(Service);
|
||||||
|
expect(container.getExtenders(Service).length, equals(0));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rebinding callbacks', () {
|
||||||
|
// Given a binding and a rebind callback
|
||||||
|
var rebound = false;
|
||||||
|
container.bind<Service>((c) => Service());
|
||||||
|
container.rebinding(Service, (c, i) => rebound = true);
|
||||||
|
|
||||||
|
// When we refresh an instance
|
||||||
|
final target = {'method': (Service s) {}};
|
||||||
|
container.refresh(Service, target, 'method');
|
||||||
|
|
||||||
|
// Then the callback should be called
|
||||||
|
expect(rebound, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('container flushing', () {
|
||||||
|
// Given some bindings and instances
|
||||||
|
container.bind<Service>((c) => Service());
|
||||||
|
container.registerSingleton(PayPalGateway());
|
||||||
|
container.registerNamedSingleton('test', 'value');
|
||||||
|
container.tag([Service], 'services');
|
||||||
|
container.when(Client).needs<Service>().give(SpecialService());
|
||||||
|
container.bindMethod('test', () {});
|
||||||
|
container.alias(PaymentGateway, PayPalGateway);
|
||||||
|
container.extend(Service, (i) {});
|
||||||
|
container.rebinding(Service, (c, i) {});
|
||||||
|
container.scoped<String>((c) => 'scoped');
|
||||||
|
container.beforeResolving<Service>((c, i) {});
|
||||||
|
|
||||||
|
// When we flush the container
|
||||||
|
container.flush();
|
||||||
|
|
||||||
|
// Then everything should be cleared
|
||||||
|
expect(container.has<Service>(), isFalse);
|
||||||
|
expect(container.hasNamed('test'), isFalse);
|
||||||
|
expect(() => container.tagged('services'), throwsStateError);
|
||||||
|
expect(container.getExtenders(Service).length, equals(0));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
447
packages/container/test/laravel_container_test.mocks.dart
Normal file
447
packages/container/test/laravel_container_test.mocks.dart
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
// Mocks generated by Mockito 5.4.4 from annotations
|
||||||
|
// in platform_illuminate_container/test/laravel_container_test.dart.
|
||||||
|
// Do not manually edit this file.
|
||||||
|
|
||||||
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
|
import 'package:mockito/mockito.dart' as _i1;
|
||||||
|
import 'package:mockito/src/dummies.dart' as _i3;
|
||||||
|
import 'package:platform_contracts/src/reflection/reflector_contract.dart'
|
||||||
|
as _i2;
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: avoid_redundant_argument_values
|
||||||
|
// ignore_for_file: avoid_setters_without_getters
|
||||||
|
// ignore_for_file: comment_references
|
||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package
|
||||||
|
// ignore_for_file: implementation_imports
|
||||||
|
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||||
|
// ignore_for_file: prefer_const_constructors
|
||||||
|
// ignore_for_file: unnecessary_parenthesis
|
||||||
|
// ignore_for_file: camel_case_types
|
||||||
|
// ignore_for_file: subtype_of_sealed_class
|
||||||
|
|
||||||
|
class _FakeReflectedTypeContract_0 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedTypeContract {
|
||||||
|
_FakeReflectedTypeContract_0(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeType_1 extends _i1.SmartFake implements Type {
|
||||||
|
_FakeType_1(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeReflectedInstanceContract_2 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedInstanceContract {
|
||||||
|
_FakeReflectedInstanceContract_2(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FakeReflectedClassContract_3 extends _i1.SmartFake
|
||||||
|
implements _i2.ReflectedClassContract {
|
||||||
|
_FakeReflectedClassContract_3(
|
||||||
|
Object parent,
|
||||||
|
Invocation parentInvocation,
|
||||||
|
) : super(
|
||||||
|
parent,
|
||||||
|
parentInvocation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectorContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectorContract extends _i1.Mock implements _i2.ReflectorContract {
|
||||||
|
MockReflectorContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? getName(Symbol? symbol) => (super.noSuchMethod(Invocation.method(
|
||||||
|
#getName,
|
||||||
|
[symbol],
|
||||||
|
)) as String?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedClassContract? reflectClass(Type? clazz) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectClass,
|
||||||
|
[clazz],
|
||||||
|
)) as _i2.ReflectedClassContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedFunctionContract? reflectFunction(Function? function) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectFunction,
|
||||||
|
[function],
|
||||||
|
)) as _i2.ReflectedFunctionContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract? reflectType(Type? type) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectType,
|
||||||
|
[type],
|
||||||
|
)) as _i2.ReflectedTypeContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract? reflectInstance(Object? object) =>
|
||||||
|
(super.noSuchMethod(Invocation.method(
|
||||||
|
#reflectInstance,
|
||||||
|
[object],
|
||||||
|
)) as _i2.ReflectedInstanceContract?);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract reflectFutureOf(Type? type) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#reflectFutureOf,
|
||||||
|
[type],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedTypeContract_0(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#reflectFutureOf,
|
||||||
|
[type],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedTypeContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedClassContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedClassContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedClassContract {
|
||||||
|
MockReflectedClassContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#annotations),
|
||||||
|
returnValue: <_i2.ReflectedInstanceContract>[],
|
||||||
|
) as List<_i2.ReflectedInstanceContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedFunctionContract> get constructors => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#constructors),
|
||||||
|
returnValue: <_i2.ReflectedFunctionContract>[],
|
||||||
|
) as List<_i2.ReflectedFunctionContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedDeclarationContract> get declarations =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#declarations),
|
||||||
|
returnValue: <_i2.ReflectedDeclarationContract>[],
|
||||||
|
) as List<_i2.ReflectedDeclarationContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#name),
|
||||||
|
returnValue: _i3.dummyValue<String>(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#name),
|
||||||
|
),
|
||||||
|
) as String);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#typeParameters),
|
||||||
|
returnValue: <_i2.ReflectedTypeParameterContract>[],
|
||||||
|
) as List<_i2.ReflectedTypeParameterContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type get reflectedType => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
returnValue: _FakeType_1(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
),
|
||||||
|
) as Type);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#isAssignableTo,
|
||||||
|
[other],
|
||||||
|
),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract newInstance(
|
||||||
|
String? constructorName,
|
||||||
|
List<dynamic>? positionalArguments, [
|
||||||
|
Map<String, dynamic>? namedArguments = const {},
|
||||||
|
List<Type>? typeArguments = const [],
|
||||||
|
]) =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedInstanceContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedInstanceContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedInstanceContract {
|
||||||
|
MockReflectedInstanceContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#type),
|
||||||
|
returnValue: _FakeReflectedTypeContract_0(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#type),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedTypeContract);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedClassContract get clazz => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#clazz),
|
||||||
|
returnValue: _FakeReflectedClassContract_3(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#clazz),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedClassContract);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract getField(String? name) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#getField,
|
||||||
|
[name],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#getField,
|
||||||
|
[name],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedFunctionContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedFunctionContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedFunctionContract {
|
||||||
|
MockReflectedFunctionContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#name),
|
||||||
|
returnValue: _i3.dummyValue<String>(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#name),
|
||||||
|
),
|
||||||
|
) as String);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#typeParameters),
|
||||||
|
returnValue: <_i2.ReflectedTypeParameterContract>[],
|
||||||
|
) as List<_i2.ReflectedTypeParameterContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#annotations),
|
||||||
|
returnValue: <_i2.ReflectedInstanceContract>[],
|
||||||
|
) as List<_i2.ReflectedInstanceContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedParameterContract> get parameters => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#parameters),
|
||||||
|
returnValue: <_i2.ReflectedParameterContract>[],
|
||||||
|
) as List<_i2.ReflectedParameterContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isGetter => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#isGetter),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isSetter => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#isSetter),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract invoke(Invocation? invocation) =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#invoke,
|
||||||
|
[invocation],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#invoke,
|
||||||
|
[invocation],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedParameterContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedParameterContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedParameterContract {
|
||||||
|
MockReflectedParameterContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#name),
|
||||||
|
returnValue: _i3.dummyValue<String>(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#name),
|
||||||
|
),
|
||||||
|
) as String);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedInstanceContract> get annotations => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#annotations),
|
||||||
|
returnValue: <_i2.ReflectedInstanceContract>[],
|
||||||
|
) as List<_i2.ReflectedInstanceContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedTypeContract get type => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#type),
|
||||||
|
returnValue: _FakeReflectedTypeContract_0(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#type),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedTypeContract);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isRequired => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#isRequired),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isNamed => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#isNamed),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [ReflectedTypeContract].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
class MockReflectedTypeContract extends _i1.Mock
|
||||||
|
implements _i2.ReflectedTypeContract {
|
||||||
|
MockReflectedTypeContract() {
|
||||||
|
_i1.throwOnMissingStub(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#name),
|
||||||
|
returnValue: _i3.dummyValue<String>(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#name),
|
||||||
|
),
|
||||||
|
) as String);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<_i2.ReflectedTypeParameterContract> get typeParameters =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#typeParameters),
|
||||||
|
returnValue: <_i2.ReflectedTypeParameterContract>[],
|
||||||
|
) as List<_i2.ReflectedTypeParameterContract>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Type get reflectedType => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
returnValue: _FakeType_1(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#reflectedType),
|
||||||
|
),
|
||||||
|
) as Type);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isAssignableTo(_i2.ReflectedTypeContract? other) => (super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#isAssignableTo,
|
||||||
|
[other],
|
||||||
|
),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i2.ReflectedInstanceContract newInstance(
|
||||||
|
String? constructorName,
|
||||||
|
List<dynamic>? positionalArguments, [
|
||||||
|
Map<String, dynamic>? namedArguments = const {},
|
||||||
|
List<Type>? typeArguments = const [],
|
||||||
|
]) =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
returnValue: _FakeReflectedInstanceContract_2(
|
||||||
|
this,
|
||||||
|
Invocation.method(
|
||||||
|
#newInstance,
|
||||||
|
[
|
||||||
|
constructorName,
|
||||||
|
positionalArguments,
|
||||||
|
namedArguments,
|
||||||
|
typeArguments,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) as _i2.ReflectedInstanceContract);
|
||||||
|
}
|
86
packages/container/test/stubs.dart
Normal file
86
packages/container/test/stubs.dart
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Test classes ported from Laravel's ContainerTest.php
|
||||||
|
|
||||||
|
// Basic concrete class
|
||||||
|
class ContainerConcreteStub {}
|
||||||
|
|
||||||
|
// Interface and implementations
|
||||||
|
abstract class IContainerContractStub {
|
||||||
|
String getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerImplementationStub implements IContainerContractStub {
|
||||||
|
final String value;
|
||||||
|
ContainerImplementationStub([this.value = 'implementation']);
|
||||||
|
@override
|
||||||
|
String getValue() => value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerImplementationStubTwo implements IContainerContractStub {
|
||||||
|
@override
|
||||||
|
String getValue() => 'implementation2';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes with dependencies
|
||||||
|
class ContainerDependentStub {
|
||||||
|
final IContainerContractStub impl;
|
||||||
|
ContainerDependentStub(this.impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerNestedDependentStub {
|
||||||
|
final ContainerDependentStub inner;
|
||||||
|
ContainerNestedDependentStub(this.inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes with default values
|
||||||
|
class ContainerDefaultValueStub {
|
||||||
|
final ContainerConcreteStub stub;
|
||||||
|
final String default_;
|
||||||
|
ContainerDefaultValueStub(this.stub, [this.default_ = 'taylor']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes with mixed parameters
|
||||||
|
class ContainerMixedPrimitiveStub {
|
||||||
|
final int first;
|
||||||
|
final ContainerConcreteStub stub;
|
||||||
|
final int last;
|
||||||
|
ContainerMixedPrimitiveStub(this.first, this.stub, this.last);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes for variable injection
|
||||||
|
class ContainerInjectVariableStub {
|
||||||
|
final String something;
|
||||||
|
ContainerInjectVariableStub(ContainerConcreteStub concrete, this.something);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContainerInjectVariableStubWithInterface
|
||||||
|
implements IContainerContractStub {
|
||||||
|
final String something;
|
||||||
|
ContainerInjectVariableStubWithInterface(
|
||||||
|
ContainerConcreteStub concrete, this.something);
|
||||||
|
@override
|
||||||
|
String getValue() => something;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class for contextual binding
|
||||||
|
class ContainerContextualBindingCallTarget {
|
||||||
|
IContainerContractStub work(IContainerContractStub stub) => stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classes for circular dependency testing
|
||||||
|
class CircularAStub {
|
||||||
|
CircularAStub(CircularBStub b);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircularBStub {
|
||||||
|
CircularBStub(CircularCStub c);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircularCStub {
|
||||||
|
CircularCStub(CircularAStub a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional test types
|
||||||
|
class StubAlias implements IContainerContractStub {
|
||||||
|
@override
|
||||||
|
String getValue() => 'alias';
|
||||||
|
}
|
Loading…
Reference in a new issue