doGetSingleton method
- @protected
- String name, {
- bool allowEarlyReference = true,
- ObjectFactory<
Object> ? factory,
inherited
Get the singleton instance for the given name.
This method is used to retrieve the singleton instance for the given name.
name: The name of the singleton to retrieve
allowEarlyReference: Whether to allow early references to the singleton
factory: The factory to use to create the singleton if necessary
Example:
final userService = registry.doGetSingleton('userService');
Implementation
@protected
Future<TypedInstance?> doGetSingleton(String name, {bool allowEarlyReference = true, ObjectFactory<Object>? factory}) async {
if(factory != null) {
return synchronized(_singletons, () async {
// 1️⃣ Check if already created
ObjectHolder<Object>? singleton = _singletons[name];
Object? result = singleton?.getValue();
Class? resultType = singleton?.getType();
if (result == null) {
// 2️⃣ Prevent creation during destruction phase
if (_singletonsCurrentlyInDestruction) {
throw PodCreationNotAllowedException(
name: name,
'Singleton pod creation not allowed while singletons of this factory are in destruction (Do not request a pod from a PodFactory in a destroy method implementation!)'
);
}
if (_logger.getIsTraceEnabled()) {
_logger.trace("Creating shared instance of pod $name");
}
// 3️⃣ Mark as in creation
try {
beforeSingletonCreation(name);
} on PodCurrentlyInCreationException catch (_) {
_singletonFactories[name] = factory;
final cached = await getSingletonCache(name, allowEarlyReference);
if (cached != null) {
final resultType = cached.getType();
if (resultType != null) {
_singletonTypes[name] = resultType;
}
return TypedInstance(cached.getValue(), resultType);
}
beforeSingletonCreation(name);
}
bool newSingleton = false;
bool recordSuppressedExceptions = (_suppressedExceptions.get()?.isEmpty ?? true);
if (recordSuppressedExceptions) {
_suppressedExceptions.get()?.clear();
}
try {
singleton = await factory.get();
result = singleton.getValue();
resultType = singleton.getType();
newSingleton = true;
} on IllegalStateException catch (_) {
// If factory indicates the state changed and the singleton implicitly appeared,
// prefer the cache instance if present; otherwise rethrow.
singleton = _singletons[name];
if (singleton == null) {
rethrow;
}
result = singleton.getValue();
resultType = singleton.getType();
} catch (e) {
if (recordSuppressedExceptions) {
for (final ex in _suppressedExceptions.get()!) {
onSuppressedException(ex);
}
}
rethrow;
} finally {
if (recordSuppressedExceptions) {
_suppressedExceptions.get()?.clear();
}
afterSingletonCreation(name);
}
// If we created the singleton, register it (tolerate implicit duplicate)
if (newSingleton) {
try {
addSingleton(name, object: singleton);
} on IllegalStateException catch (_) {
// Another concurrent path may have registered the same pod.
// Accept the existing instance if it's identical; otherwise rethrow.
final existing = _singletons[name];
if (result != existing?.getValue()) {
rethrow;
}
}
}
}
if (resultType != null) {
_singletonTypes[name] = resultType;
}
return TypedInstance(result, resultType);
});
} else {
final singleton = await getSingletonCache(name, allowEarlyReference);
if (singleton != null) {
return TypedInstance(singleton.getValue(), singleton.getType());
} else {
return null;
}
}
}