Skip to content

Instantly share code, notes, and snippets.

@themisir
Created April 20, 2021 20:19
Show Gist options
  • Save themisir/8464f40a9d618f5d811033fa11f01780 to your computer and use it in GitHub Desktop.
Save themisir/8464f40a9d618f5d811033fa11f01780 to your computer and use it in GitHub Desktop.
typedef Func<T> = T Function();
abstract class ServiceDefinition<T> {
factory ServiceDefinition.singleton(T instance) = _SingletonServiceDefinition;
factory ServiceDefinition.factory(Func<T> create) = _FactoryServiceDefinition;
const ServiceDefinition._();
T instantiate();
bool matches<E>() => E == T;
}
class ServiceCollection {
ServiceCollection() : services = <ServiceDefinition>[];
final List<ServiceDefinition> services;
void register(ServiceDefinition definition) => services.add(definition);
T? findService<T>() {
for (final definition in services) {
if (definition.matches<T>()) {
return definition.instantiate() as T;
}
}
}
T requireService<T>() {
for (final definition in services) {
if (definition.matches<T>()) {
return definition.instantiate() as T;
}
}
throw Exception('Service is not registered');
}
}
class Locator {
Locator() : _collection = ServiceCollection();
final ServiceCollection _collection;
void registerSingleton<T>(T instance) {
_collection.register(ServiceDefinition<T>.singleton(instance));
}
void registerFactory<T>(Func<T> create) {
_collection.register(ServiceDefinition<T>.factory(create));
}
void register(ServiceDefinition definition) {
_collection.register(definition);
}
T get<T>() => _collection.requireService<T>();
}
class _SingletonServiceDefinition<T> extends ServiceDefinition<T> {
const _SingletonServiceDefinition(this.instance) : super._();
final T instance;
@override
T instantiate() => instance;
}
class _FactoryServiceDefinition<T> extends ServiceDefinition<T> {
const _FactoryServiceDefinition(this.create) : super._();
final Func<T> create;
@override
T instantiate() => create();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment