dart_service_provider 1.2.3
dart_service_provider: ^1.2.3 copied to clipboard
A services dependency provider, like dependency inject, easy to learn and easy to use.
dart_service_provider #
A services dependency provider, like dependency inject, easy to learn and easy to use.
Announcement:The service_container package is recommended, it does not require the service container to be built in advance, and it does not need to enumerate the service descriptor collection when getting the service instance, so it has faster performance.
Features #
Provide services life time control with singleton, scoped, transient.
Getting started #
void main() {
final services = ServiceCollection()
// add the default logging services
..addLogging()
..addSingleton<IMySingletonService, MySingletonService>((_) => MySingletonService())
..addScoped<IMyScopedService, MyScopedService>((_) => MyScopedService())
..addTransient<IMyTransientService, MyTransientService>((_) => MyTransientService())
..addScoped<MyScopedDependencyService, MyScopedDependencyService>(
(p) =>
MyScopedDependencyService(
singletonService: p.getRequiredService<IMySingletonService>(),
scopedService: p.getRequiredService<IMyScopedService>(),
transientService: p.getRequiredService<IMyTransientService>(),
),
);
final serviceProvider = services.buildServiceProvider();
final singletonService = serviceProvider.getRequiredService<IMySingletonService>();
final transientService = serviceProvider.getRequiredService<IMyTransientService>();
// Scoping
final scope = serviceProvider.createScope();
final singletonService2 = scope.serviceProvider.getRequiredService<IMySingletonService>();
assert(identical(singletonService, singletonService2));
final scopedService = scope.serviceProvider.getRequiredService<IMyScopedService>();
final scopedService2 = scope.serviceProvider.getRequiredService<IMyScopedService>();
assert(identical(scopedService, scopedService2));
final transientService2 = scope.serviceProvider.getRequiredService<IMyTransientService>();
assert(!identical(transientService, transientService2));
// Always dispose the scope when you don't need it anymore.
// This will cleanup any resources use by this scope and the services in this scope.
// There is a `disposeAsync()` method for asynchronous calls.
// Note that: `dispose` method from interface `IDisposable` and `disposeAsync` from interface `IAsyncDisposable`
// Any services that it implements `IDisposable` or `IAsyncDisposable` and constructed by `IServiceProvider` will be disposed when its life is end automatically.
scope.dispose();
// Always dispose the ServiceProvider when you don't need it anymore.
// There also is a `disposeAsync()` method
serviceProvider.dispose();
}
abstract interface class IMySingletonService implements IDisposable {}
class MySingletonService implements IMySingletonService {
MySingletonService() {
print("MySingletonService $hashCode constructing");
}
@override
void dispose() {
print("MySingletonService $hashCode disposing");
}
}
abstract interface class IMyScopedService implements IAsyncDisposable {}
class MyScopedService implements IMyScopedService {
MyScopedService() {
print("MyScopedService $hashCode constructing");
}
@override
Future<void> disposeAsync() {
print("MyScopedService $hashCode disposing asynchronous");
return Future<void>.value();
}
}
abstract interface class IMyTransientService implements IDisposable {}
class MyTransientService implements IMyTransientService {
MyTransientService() {
print("MyTransientService $hashCode constructing");
}
@override
void dispose() {
print("MyTransientService $hashCode disposing");
}
}
class MyScopedDependencyService {
final IMySingletonService singletonService;
final IMyScopedService scopedService;
final IMyTransientService transientService;
MyScopedDependencyService(
{required this.singletonService, required this.scopedService, required this.transientService}) {
print("MyDependencyService $hashCode constructing with "
"IMySingletonService ${singletonService.hashCode}, "
"IMyScopedService ${scopedService.hashCode}, "
"IMyTransientService ${transientService.hashCode}");
}
}
Usage #
void main() {
final services = ServiceCollection();
services.addSingleton<MyService, MyService>((_) => MyService());
final rootProvider = services.buildServiceProvider();
final myService = rootProvider.getRequiredService<MyService>();
// myService.foo()
}
class MyService {}
Logging #
Enable default logging
final services = ServiceCollection()
// add the default logging services
..addLogging();
Custom logging:
final services = ServiceCollection()
// add the default logging services
..addLogging((loggingBuilder) {
// Custom your logging services
});
How to custom logging services:
- Implement
ILoggerFactoryinterface, then calladdLoggingextension method onServiceCollection, Specify theconfigargument. - Optional implement
ILoggerandILogger4interfaces, implementILogger4is recommended. - If you implementations does not need
LoggerOptionsservice, please call theLoggingBuilderExtensions.removeOptionsextension method to delete it.
Environment #
Provide environment service.
void main() {
final services = ServiceCollection();
// Add environment service
services.addEnvironment<Evironment>(Environment(name: Environments.production));
final provider = services.buildServiceProvider();
final env = provider.getRequiredService<IEnvironment>();
print(env.isProduction); // true
}
You can detect the environment and change the application behavior at runtime.
Service configuration #
After any service that implements IConfigurable is created from the service container (including
singleton services that specify instances), the service container will look for its corresponding
ServiceConfigure<TService> and ServicePostConfigure<TService> services to configure these
service instances.
Use the serviceCollection.configure<TService> method or the
serviceCollection.postConfigure<TService> method to add a configuration service for a configurable
service.
Additional information #
If you have any issues or suggests please redirect to repo or send an email to me.
Flutter #
In flutter, you can use flutter_service_provider.