dart_dependency_injection 1.1.3+2 copy "dart_dependency_injection: ^1.1.3+2" to clipboard
dart_dependency_injection: ^1.1.3+2 copied to clipboard

The most powerful dependency injection library for Dart.

Dart Dependency Injection #

This library is inspired by ioc_container, thanks to the author.

Getting Started #

Create a ServiceCollection:

var collection = ServiceCollection();

Add services to the ServiceCollection:

// Add a transient service:
collection.add<TestService>((serviceProvider) => TestService());

// Add a singleton service:
collection.addSingleton<TestSingletonService>((serviceProvider) => TestSingletonService());

// Add a scoped singleton service:
collection.addScopedSingleton<TestScopedSingletonService>((serviceProvider) => TestScopedSingletonService());

Build a ServiceProvider:

var provider = collection.build();

Get services from the ServiceProvider:

var testService = provider.get<TestService>();

ServiceProvider #

Adding Services #

create a ServiceCollection:

var collection = ServiceCollection();

Add Singleton

collection.addSingleton<TestSingletonService>((serviceProvider) => TestSingletonService());

A singleton service has only one instance in the current scope as well as any derived scopes.

Add Scoped Singleton

collection.addScopedSingleton<TestScopedSingletonService>((serviceProvider) => TestScopedSingletonService());

A scoped singleton service gets a different instance for each scope it is requested from. Within the same scope, the service will always return the same instance.

Add Transient

collection.add<TestService>((serviceProvider) => TestService());

A transient service will create a new instance every time it is got.

Build a ServiceProvider #

var collection = ServiceCollection();
// ... add some services
var serviceProvider = ServiceProvider build();

After building the ServiceProvider, you will no longer be able to add services, but you can build the scope.

Build a Scope ServiceProvider #

var collection = ServiceCollection();
// ... add some services
var parentProvider = ServiceProvider build();
// build a scope
var scopedServiceProvider = parentProvider.buildScoped(
  builder: (collection) {
    // ... add some services
  },
);

Scoped service providers will inherit all services from the parent and additional services can be added

Service #

Get service instance #

TestService testService = provider.get<TestService>();
// or
TestService testService = provider.getByType(TestService);

Will throw an exception if the service does not exist

or

TestService? testService = provider.tryGet<TestService>();
// or
TestService? testService = provider.tryGetType(TestService);

Returns null if the service does not exist

Service scope #

for singleton service, its scope is always the one where it was defined.

for scoped singleton service, its scope is the one where it was created.

for transient service, its scope is the one where it was created.

Service Initialization #

If the injected service with the DependencyInjectionService and overrides the dependencyInjectionServiceInitialize method, that method will be executed immediately after creation.

Write the initialization code as follows:

class TestService with DependencyInjectionService {
  @override
  FutureOr dependencyInjectionServiceInitialize(){
    print("run at service create");
  }
}

The dependencyInjectionServiceInitialize method can be async, and two methods in the ServiceProvider can be used to wait for async initialization:

/// Wait for the most recently requested service to initialize. Must be called immediately after getting a service.
FutureOr waitLatestServiceInitialize();

/// Wait for all currently initializing services to finish.
FutureOr waitServicesInitialize();

initializeWhenServiceProviderBuilt #

there is a parameter initializeWhenServiceProviderBuilt when adding a service, if it is set to true, the service will be created once immediately after generating the ServiceProvider and then initialized.

some codes like this:

var collection = ServiceCollection();
collection.add<TestService>((serviceProvider) => TestService(), initializeWhenServiceProviderBuilt: true);
var provider = collection.build();
// TestService will be created once and initialized immediately

ServiceObserver #

ServiceObserver is an interface that can be implemented to observe the creation, initialization, and disposal of services.

abstract class ServiceObserver<T> {
  void onServiceCreated(T service);
  void onServiceInitializeDone(T service);
  void onServiceDispose(T service);
}

Add observer for every services #

var collection = ServiceCollection();
// ...add some services
collection.add<ServiceObserver>((serviceProvider) => TestServiceObserver());

When the service is created, a ServiceObserver service will be created to observer this service.

Add observer for a service #

var collection = ServiceCollection();
// ...add some services
collection.add<ServiceObserver<TestService>>((serviceProvider) => TestServiceObserver());

only the TestService and its subclasses will be observed.

DependencyInjectionService #

DependencyInjectionService is a mixin that provides some magic methods for services created by dependency injection.

/// Get a service.
T getService<T extends Object>();

/// Try to get a service. Returns null if the service does not exist.
T? tryGetService<T extends Object>();

/// Get a service by type.
dynamic getServiceByType(Type type);

/// Try to get a service by type. Returns null if the service does not exist.
dynamic tryGetServiceByType(Type type);

/// Wait for the most recently requested service to initialize. Must be called immediately after getting a service.
FutureOr waitLatestServiceInitialize();

/// Wait for all currently initializing services to finish.
FutureOr waitServicesInitialize();

/// Create a scope
ServiceProvider buildScopedServiceProvider<T>({void Function(ServiceCollection)? builder, Object? scope});

Use these methods just like using the ServiceProvider in your scope.

ServiceProvider Dispose #

Call the dispose method of ServiceProvider. ServiceProvider also calls dispose for all alive services and all subscopes.

Service Dispose #

Any service can call the dispose method itself. After dispose, you will not be able to use any method of DependencyInjectionService. And the scope built using the buildScopedServiceProvider method of DependencyInjectionService will also dispose.

The service's dispose is usually called automatically :

for singleton service, Call dispose when defining its scope dispose.

for scoped singleton service, Call dispose when the scope is disposed.

for transient service :

If you don't use it anymore, it may be cleared by GC at any time.

When it is cleared by GC, the ServiceProvider built by its buildScopedServiceProvider method will call dispose.

If it is still alive, it will be called dispose when the ServiceProvider disposes it.

3
likes
150
pub points
66%
popularity

Publisher

verified publisherybz.im

The most powerful dependency injection library for Dart.

Repository (GitHub)
View/report issues

Topics

#dependency-injection

Documentation

API reference

License

MIT (LICENSE)

Dependencies

collection, meta

More

Packages that depend on dart_dependency_injection