예제 #1
0
        private Task <FeatureEntry> LoadFeatureAsync(IFeatureInfo feature)
        {
            return(_features.GetOrAdd(feature.Id,
                                      new Lazy <Task <FeatureEntry> >(async() =>
            {
                var loadedExtension = await LoadExtensionAsync(feature.Extension);

                if (loadedExtension.IsError)
                {
                    return new NonCompiledFeatureEntry(feature);
                }

                var extensionTypes = loadedExtension
                                     .ExportedTypes
                                     .Where(t => t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract);

                var featureTypes = new List <Type>();

                foreach (var type in extensionTypes)
                {
                    string sourceFeature = GetSourceFeatureNameForType(type, feature.Id);
                    if (sourceFeature == feature.Id)
                    {
                        featureTypes.Add(type);
                        _typeFeatureProvider.TryAdd(type, feature);
                    }
                }

                return new CompiledFeatureEntry(feature, featureTypes);
            })).Value);
        }
예제 #2
0
        private IEnumerable <Feature> BuiltinFeatures()
        {
            var projectContext = ProjectContext.CreateContextForEachFramework("").FirstOrDefault();

            var additionalLibraries = projectContext.LibraryManager
                                      .GetLibraries()
                                      .Where(x => x.Identity.Name.StartsWith("Orchard"));

            var features = new List <Feature>();

            foreach (var additonalLib in additionalLibraries)
            {
                var assembly = Assembly.Load(new AssemblyName(additonalLib.Identity.Name));

                var feature = new Feature
                {
                    Descriptor = new FeatureDescriptor
                    {
                        Id        = additonalLib.Identity.Name,
                        Extension = new ExtensionDescriptor
                        {
                            Id = additonalLib.Identity.Name
                        }
                    },
                    ExportedTypes =
                        assembly.ExportedTypes
                        .Where(t => t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract)
                        //.Except(new[] { typeof(DefaultOrchardHost) })
                        .ToArray()
                };

                features.Add(feature);

                // Register built-in features in the type provider

                // TODO: Prevent this code from adding the services from modules as it's already added
                // by the extension loader.

                if (!_builtinFeatureRegistered)
                {
                    foreach (var type in feature.ExportedTypes)
                    {
                        _typeFeatureProvider.TryAdd(type, feature);
                    }
                }
            }

            _builtinFeatureRegistered = true;

            return(features);
        }
예제 #3
0
        private Feature LoadFeature(FeatureDescriptor featureDescriptor)
        {
            lock (_features)
            {
                if (_logger.IsEnabled(LogLevel.Information))
                {
                    _logger.LogInformation("Loading feature {0}", featureDescriptor.Name);
                }

                if (_features.ContainsKey(featureDescriptor.Id))
                {
                    if (_logger.IsEnabled(LogLevel.Debug))
                    {
                        _logger.LogDebug("Feature {0} loaded from cache", featureDescriptor.Name);
                    }

                    return(_features[featureDescriptor.Id]);
                }

                var extensionDescriptor = featureDescriptor.Extension;
                var featureId           = featureDescriptor.Id;
                var extensionId         = extensionDescriptor.Id;

                var extensionEntry = LoadExtension(extensionDescriptor);

                Feature feature;
                if (extensionEntry == null)
                {
                    // If the feature could not be compiled for some reason,
                    // return a "null" feature, i.e. a feature with no exported types.
                    feature = new Feature
                    {
                        Descriptor    = featureDescriptor,
                        ExportedTypes = Enumerable.Empty <Type>()
                    };

                    _features.Add(featureDescriptor.Id, feature);
                    return(feature);
                }

                var extensionTypes = extensionEntry.ExportedTypes.Where(t => t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract);
                var featureTypes   = new List <Type>();

                foreach (var type in extensionTypes)
                {
                    string sourceFeature = GetSourceFeatureNameForType(type, extensionId);
                    if (String.Equals(sourceFeature, featureId, StringComparison.OrdinalIgnoreCase))
                    {
                        featureTypes.Add(type);
                    }
                }

                feature = new Feature
                {
                    Descriptor    = featureDescriptor,
                    ExportedTypes = featureTypes
                };

                foreach (var type in feature.ExportedTypes)
                {
                    _typeFeatureProvider.TryAdd(type, feature);
                }


                _features.Add(featureDescriptor.Id, feature);
                return(feature);
            }
        }
예제 #4
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;
            }
        }
예제 #5
0
        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();
            }
        }
예제 #6
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 manifestConfiguration = _manifestOptions
                                                .ManifestConfigurations
                                                .FirstOrDefault(mc =>
                    {
                        return(module.ModuleInfo.Type.Equals(mc.Type, StringComparison.OrdinalIgnoreCase));
                    });

                    if (manifestConfiguration == null)
                    {
                        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;
            }
        }
예제 #7
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;
            }
        }
예제 #8
0
        private void EnsureInitialized()
        {
            if (_isInitialized)
            {
                return;
            }

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

                var moduleNames   = _hostingEnvironment.GetApplication().NamedModules;
                var loadedPlugins = new ConcurrentDictionary <string, PluginEntry>();

                Parallel.ForEach(moduleNames, new ParallelOptions {
                    MaxDegreeOfParallelism = 8
                }, (name) =>
                {
                    var module = _hostingEnvironment.GetModule(name.Name);

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

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

                    var entry = new PluginEntry
                    {
                        PluginInfo    = pluginInfo,
                        Assembly      = module.Assembly,
                        ExportedTypes = module.Assembly.ExportedTypes
                    };

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

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

                var allTypesByExtension = loadedPlugins.SelectMany(extension =>
                                                                   extension.Value.ExportedTypes.Where(IsComponentType)
                                                                   .Select(type => new
                {
                    PluginEntry = extension.Value,
                    Type        = type
                })).ToArray();

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

                foreach (var loadedExtension in loadedPlugins)
                {
                    var plugin = loadedExtension.Value;

                    foreach (var feature in plugin.PluginInfo.Features)
                    {
                        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));
                    }
                }
                ;

                _featureInfos = Order(loadedFeatures.Values.Select(f => f.FeatureInfo));
                _features     = _featureInfos.ToDictionary(f => f.Id, f => loadedFeatures[f.Id]);

                _pluginInfos = _featureInfos.Where(f => f.Id == f.Plugin.Features.First().Id)
                               .Select(f => f.Plugin);

                _plugins = _pluginInfos.ToDictionary(e => e.Id, e => loadedPlugins[e.Id]);

                _isInitialized = true;
            }
        }