Environment constructor
Environment({
- Type? forModule,
- Environment? parent,
- List<
String> ? features,
Create a new Environment
forModule the module class that determines the classes which will be manged
parent optional parent environment, whose objects will be inherited
features list of feature that this environment defines. See Conditional
Implementation
Environment({Type? forModule, this.parent, List<String>? features}) : module = forModule, features = features ?? []{
if ( parent == null )
if ( module == Boot) {
lifecycleProcessors[0].add(OnInjectProcessor());
lifecycleProcessors[1].add(OnInitProcessor());
lifecycleProcessors[2].add(OnRunningProcessor());
lifecycleProcessors[3].add(OnDestroyProcessor());
}
else parent = Boot.getEnvironment();
final Stopwatch stopwatch = Stopwatch()..start();
if ( Tracer.enabled )
Tracer.trace('di', TraceLevel.low, 'create environment for module $module');
// inherit parent providers
if (parent != null) {
parent!.providers.forEach((providerType, inheritedProvider) {
var provider = inheritedProvider;
if (inheritedProvider.scope == 'environment') {
providers[providerType] = (inheritedProvider as EnvironmentInstanceProvider).copy(this);
}
else providers[providerType] = provider;
});
// inherit lifecycle processors
for (int lifecycle = 0; lifecycle < 4; lifecycle++)
for (final processor in parent!.lifecycleProcessors[lifecycle]) {
if (providers[processor.runtimeType]?.scope != 'environment') {
lifecycleProcessors[lifecycle].add(processor);
}
else {
get(type: processor.runtimeType); // automatically appends
}
}
}
else {
// add bootstrap provider for Boot
providers[SingletonScope] = SingletonScopeInstanceProvider();
providers[RequestScope] = RequestScopeInstanceProvider();
providers[EnvironmentScope] = EnvironmentScopeInstanceProvider();
}
final Set<TypeDescriptor> loadedModules = {};
final List<RegExp> filter = [];
// filter by module prefix
bool filterProvider(AbstractInstanceProvider provider) {
final hostModule = TypeDescriptor.forType(provider.host).module;
//print("filter $provider");
for (final fileFilter in filter) {
if (fileFilter.hasMatch(hostModule)) {
//print("ok");
return true;
}
}
//print("na");
return false;
}
RegExp buildModuleRegex(String modulePath, {bool includeChildren = false, bool includeSiblings = false}) {
final lastSlash = modulePath.lastIndexOf('/');
final dir = lastSlash >= 0 ? modulePath.substring(0, lastSlash) : '';
//final fileOrDir = lastSlash >= 0 ? modulePath.substring(lastSlash + 1) : modulePath;
String pattern;
if (!includeChildren && !includeSiblings) {
pattern = '^' + RegExp.escape(modulePath) + r'$';
}
else if (includeSiblings && !includeChildren) {
pattern = '^' + (dir.isNotEmpty ? RegExp.escape(dir) + '/' : '') + r'[^/]+$';
}
else if (!includeSiblings && includeChildren) {
pattern = '^' + (dir.isNotEmpty ? RegExp.escape(dir) + '/' : '') + r'.+$';
}
else {
// both children and siblings
pattern = '^' + (dir.isNotEmpty ? RegExp.escape(dir) + '/' : '') + r'.+$';
}
return RegExp(pattern);
}
// recursively load environment and its dependencies
void loadModule(TypeDescriptor moduleDescriptor) {
if (!loadedModules.contains(moduleDescriptor)) {
if ( Tracer.enabled )
Tracer.trace('di', TraceLevel.low, 'load environment $moduleDescriptor');
loadedModules.add(moduleDescriptor);
final decorator = moduleDescriptor.findAnnotation<Module>();
if (decorator == null) {
throw DIRegistrationException('$moduleDescriptor is not an module class');
}
// load dependencies recursively
for (final import in decorator.imports) {
loadModule(TypeDescriptor.forType(import));
}
// determine package prefix
final module = moduleDescriptor.getAnnotation<Module>()!;
final packageName = moduleDescriptor.module;
if (packageName.isNotEmpty) {
filter.add(buildModuleRegex(packageName, includeChildren: module.includeSubdirectories, includeSiblings: module.includeSiblings));
}
}
}
if ( module != null) {
loadModule(TypeDescriptor.forType(module));
// filter providers according to prefix list
providers.addAll(Providers.filter(this, filterProvider));
// construct eager objects for local providers
for (final provider in providers.values.toSet()) {
if (provider.eager) {
provider.create(this);
}
}
} // if
// run lifecycle callbacks
for (final instance in instances) {
executeProcessors(null, Lifecycle.onRunning, instance);
}
stopwatch.stop();
if ( Tracer.enabled )
Tracer.trace('di', TraceLevel.high, 'created environment for module $module in ${stopwatch.elapsedMilliseconds} ms, created ${instances.length} instances');
}