private async Task EnsureInitializedAsync()
        {
            if (_isInitialized)
            {
                return;
            }

            await _semaphore.WaitAsync();

            try
            {
                if (_isInitialized)
                {
                    return;
                }

                var modules          = _applicationContext.Application.Modules;
                var loadedExtensions = new ConcurrentDictionary <string, ExtensionEntry>();

                // Load all extensions in parallel
                await modules.ForEachAsync((module) =>
                {
                    if (!module.ModuleInfo.Exists)
                    {
                        return(Task.CompletedTask);
                    }
                    var manifestInfo = new ManifestInfo(module.ModuleInfo);

                    var extensionInfo = new ExtensionInfo(module.SubPath, manifestInfo, (mi, ei) =>
                    {
                        return(_featuresProvider.GetFeatures(ei, mi));
                    });

                    var entry = new ExtensionEntry
                    {
                        ExtensionInfo = extensionInfo,
                        Assembly      = module.Assembly,
                        ExportedTypes = module.Assembly.ExportedTypes
                    };

                    loadedExtensions.TryAdd(module.Name, entry);

                    return(Task.CompletedTask);
                });

                var loadedFeatures = new Dictionary <string, FeatureEntry>();

                // Get all valid types from any extension
                var allTypesByExtension = loadedExtensions.SelectMany(extension =>
                                                                      extension.Value.ExportedTypes.Where(IsComponentType)
                                                                      .Select(type => new
                {
                    ExtensionEntry = extension.Value,
                    Type           = type
                })).ToArray();

                var typesByFeature = allTypesByExtension
                                     .GroupBy(typeByExtension => GetSourceFeatureNameForType(
                                                  typeByExtension.Type,
                                                  typeByExtension.ExtensionEntry.ExtensionInfo.Id))
                                     .ToDictionary(
                    group => group.Key,
                    group => group.Select(typesByExtension => typesByExtension.Type).ToArray());

                foreach (var loadedExtension in loadedExtensions)
                {
                    var extension = loadedExtension.Value;

                    foreach (var feature in extension.ExtensionInfo.Features)
                    {
                        // Features can have no types
                        if (typesByFeature.TryGetValue(feature.Id, out var featureTypes))
                        {
                            foreach (var type in featureTypes)
                            {
                                _typeFeatureProvider.TryAdd(type, feature);
                            }
                        }
                        else
                        {
                            featureTypes = Array.Empty <Type>();
                        }

                        loadedFeatures.Add(feature.Id, new CompiledFeatureEntry(feature, featureTypes));
                    }
                }
                ;

                // Feature infos and entries are ordered by priority and dependencies.
                _featureInfos = Order(loadedFeatures.Values.Select(f => f.FeatureInfo));
                _features     = _featureInfos.ToDictionary(f => f.Id, f => loadedFeatures[f.Id]);

                // Extensions are also ordered according to the weight of their first features.
                _extensionsInfos = _featureInfos.Where(f => f.Id == f.Extension.Features.First().Id)
                                   .Select(f => f.Extension);

                _extensions = _extensionsInfos.ToDictionary(e => e.Id, e => loadedExtensions[e.Id]);

                _isInitialized = true;
            }
            finally
            {
                _semaphore.Release();
            }
        }
Beispiel #2
0
        private void EnsureInitialized()
        {
            if (_isInitialized)
            {
                return;
            }

            lock (InitializationSyncLock)
            {
                if (_isInitialized)
                {
                    return;
                }

                var moduleNames      = _hostingEnvironment.GetApplication().ModuleNames;
                var loadedExtensions = new ConcurrentDictionary <string, ExtensionEntry>();

                // Load all extensions in parallel
                Parallel.ForEach(moduleNames, new ParallelOptions {
                    MaxDegreeOfParallelism = 8
                }, (name) =>
                {
                    var module = _hostingEnvironment.GetModule(name);

                    if (!module.ModuleInfo.Exists)
                    {
                        return;
                    }
                    var manifestInfo = new ManifestInfo(module.ModuleInfo);

                    var extensionInfo = new ExtensionInfo(module.SubPath, manifestInfo, (mi, ei) => {
                        return(_featuresProvider.GetFeatures(ei, mi));
                    });

                    var entry = new ExtensionEntry
                    {
                        ExtensionInfo = extensionInfo,
                        Assembly      = module.Assembly,
                        ExportedTypes = module.Assembly.ExportedTypes
                    };

                    loadedExtensions.TryAdd(module.Name, entry);
                });

                var loadedFeatures = new Dictionary <string, FeatureEntry>();

                // Get all valid types from any extension
                var allTypesByExtension = loadedExtensions.SelectMany(extension =>
                                                                      extension.Value.ExportedTypes.Where(IsComponentType)
                                                                      .Select(type => new
                {
                    ExtensionEntry = extension.Value,
                    Type           = type
                })).ToArray();

                var typesByFeature = allTypesByExtension
                                     .GroupBy(typeByExtension => GetSourceFeatureNameForType(
                                                  typeByExtension.Type,
                                                  typeByExtension.ExtensionEntry.ExtensionInfo.Id))
                                     .ToDictionary(
                    group => group.Key,
                    group => group.Select(typesByExtension => typesByExtension.Type).ToArray());

                foreach (var loadedExtension in loadedExtensions)
                {
                    var extension = loadedExtension.Value;

                    foreach (var feature in extension.ExtensionInfo.Features)
                    {
                        // Features can have no types
                        if (typesByFeature.TryGetValue(feature.Id, out var featureTypes))
                        {
                            foreach (var type in featureTypes)
                            {
                                _typeFeatureProvider.TryAdd(type, feature);
                            }
                        }
                        else
                        {
                            featureTypes = Array.Empty <Type>();
                        }

                        loadedFeatures.Add(feature.Id, new CompiledFeatureEntry(feature, featureTypes));
                    }
                }
                ;

                // Feature infos and entries are ordered by priority and dependencies.
                _featureInfos = Order(loadedFeatures.Values.Select(f => f.FeatureInfo));
                _features     = _featureInfos.ToDictionary(f => f.Id, f => loadedFeatures[f.Id]);

                // Extensions are also ordered according to the weight of their first features.
                _extensionsInfos = _featureInfos.Where(f => f.Id == f.Extension.Features.First().Id)
                                   .Select(f => f.Extension);

                _extensions = _extensionsInfos.ToDictionary(e => e.Id, e => loadedExtensions[e.Id]);

                _isInitialized = true;
            }
        }