public Task <ExtensionEntry> LoadExtensionAsync(IExtensionInfo extensionInfo) { // Results are cached so that there is no mismatch when loading an assembly twice. // Otherwise the same types would not match. return(_extensions.GetOrAdd(extensionInfo.Id, async id => { var extension = _extensionLoader.Load(extensionInfo); if (extension.IsError && _logger.IsEnabled(LogLevel.Warning)) { _logger.LogWarning("No suitable loader found for extension \"{0}\"", id); } return await Task.FromResult(extension); })); }
public Task <ExtensionEntry> LoadExtensionAsync(IExtensionInfo extensionInfo) { // Results are cached so that there is no mismatch when loading an assembly twice. // Otherwise the same types would not match. return(_extensions.GetOrAdd(extensionInfo.Id, new Lazy <Task <ExtensionEntry> >(() => { var extension = _extensionLoader.Load(extensionInfo); if (extension.IsError && L.IsEnabled(LogLevel.Warning)) { L.LogError("No suitable loader found for extension \"{0}\"", extensionInfo.Id); } return Task.FromResult(extension); })).Value); }
private void EnsureInitialized() { if (_isInitialized) { return; } lock (InitializationSyncLock) { if (_isInitialized) { return; } var extensions = HarvestExtensions(); var loadedExtensions = new ConcurrentDictionary <string, ExtensionEntry>(); Parallel.ForEach(extensions, (extension) => { if (!extension.Exists) { return; } var entry = _extensionLoader.Load(extension); if (entry.IsError && L.IsEnabled(LogLevel.Warning)) { L.LogWarning("No loader found for extension \"{0}\". This might denote a dependency is missing or the extension doesn't have an assembly.", extension.Id); } loadedExtensions.TryAdd(extension.Id, entry); }); var loadedFeatures = new Dictionary <string, FeatureEntry>(); foreach (var loadedExtension in loadedExtensions) { var extension = loadedExtension.Value; var extensionTypes = extension .ExportedTypes .Where(t => t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract); foreach (var feature in extension.ExtensionInfo.Features) { var featureTypes = new HashSet <Type>(); // Search for all types from the extensions that are not assigned to a different // feature. foreach (var type in extensionTypes) { string sourceFeature = GetSourceFeatureNameForType(type, extension.ExtensionInfo.Id); if (sourceFeature == feature.Id) { featureTypes.Add(type); _typeFeatureProvider.TryAdd(type, feature); } } // Search in other extensions for types that are assigned to this feature. var otherExtensionInfos = extensions.Where(x => x.Id != extension.ExtensionInfo.Id); foreach (var otherExtensionInfo in otherExtensionInfos) { var otherExtension = loadedExtensions[otherExtensionInfo.Id]; foreach (var type in otherExtension.ExportedTypes) { string sourceFeature = GetSourceFeatureNameForType(type, null); if (sourceFeature == feature.Id) { featureTypes.Add(type); _typeFeatureProvider.TryAdd(type, feature); } } } loadedFeatures.Add(feature.Id, new CompiledFeatureEntry(feature, featureTypes)); } } ; _extensions = loadedExtensions; // Could we get rid of _allOrderedFeatureInfos and just have _features? _features = loadedFeatures; _allOrderedFeatureInfos = Order(loadedFeatures.Values.Select(x => x.FeatureInfo)); _isInitialized = true; } }
private void EnsureInitialized() { if (_isInitialized) { return; } lock (InitializationSyncLock) { if (_isInitialized) { return; } var extensions = HarvestExtensions(); var loadedExtensions = new ConcurrentDictionary <string, ExtensionEntry>(); // Load all extensions in parallel Parallel.ForEach(extensions, (extension) => { if (!extension.Exists) { return; } var entry = _extensionLoader.Load(extension); if (entry.IsError && L.IsEnabled(LogLevel.Warning)) { L.LogWarning("No loader found for extension \"{0}\". This might denote a dependency is missing or the extension doesn't have an assembly.", extension.Id); } loadedExtensions.TryAdd(extension.Id, 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)); } } ; _extensions = loadedExtensions; // Could we get rid of _allOrderedFeatureInfos and just have _features? _features = loadedFeatures; _allOrderedFeatureInfos = Order(loadedFeatures.Values.Select(x => x.FeatureInfo)); _isInitialized = true; } }