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); }
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); }
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); } }
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 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(); } }
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; } }
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; } }
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; } }