Example #1
0
        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);
            }));
        }
Example #2
0
        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);
        }
Example #3
0
        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;
            }
        }
Example #4
0
        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;
            }
        }