mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Generalize the dependy ordering algorithm
--HG-- branch : dev
This commit is contained in:
@@ -7,6 +7,7 @@ using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.State.Models;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Utility;
|
||||
|
||||
namespace Orchard.Environment.State {
|
||||
public class ShellStateCoordinator : IShellStateManagerEventHandler, IShellDescriptorManagerEventHandler {
|
||||
@@ -184,39 +185,9 @@ namespace Orchard.Environment.State {
|
||||
state.EnableState == ShellFeatureState.State.Rising;
|
||||
}
|
||||
|
||||
class Linkage {
|
||||
public FeatureDescriptor Feature {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool Used {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<FeatureDescriptor> OrderByDependencies(IEnumerable<FeatureDescriptor> descriptors) {
|
||||
var population = descriptors.Select(d => new Linkage {
|
||||
Feature = d
|
||||
}).ToArray();
|
||||
|
||||
var result = new List<FeatureDescriptor>();
|
||||
foreach (var item in population) {
|
||||
Add(item, result, population);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void Add(Linkage item, ICollection<FeatureDescriptor> list, IEnumerable<Linkage> population) {
|
||||
if (item.Used)
|
||||
return;
|
||||
|
||||
item.Used = true;
|
||||
var dependencies = item.Feature.Dependencies ?? Enumerable.Empty<string>();
|
||||
foreach (var dependency in dependencies.SelectMany(d => population.Where(p => p.Feature.Name == d))) {
|
||||
Add(dependency, list, population);
|
||||
}
|
||||
list.Add(item.Feature);
|
||||
return descriptors.OrderByDependencies((item, dep) =>
|
||||
item.Dependencies.Any(x => StringComparer.OrdinalIgnoreCase.Equals(x, dep.Name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -402,6 +402,7 @@
|
||||
<Compile Include="Environment\Extensions\Compilers\CSharpExtensionBuildProviderShim.cs" />
|
||||
<Compile Include="Environment\Extensions\Compilers\ProjectFileDescriptor.cs" />
|
||||
<Compile Include="Environment\Extensions\Compilers\IProjectFileParser.cs" />
|
||||
<Compile Include="Utility\DependencyOrderingUtility.cs" />
|
||||
<Compile Include="Environment\IOrchardHostContainer.cs" />
|
||||
<Compile Include="Environment\IShim.cs" />
|
||||
<Compile Include="Environment\OrchardHostContainerRegistry.cs" />
|
||||
|
41
src/Orchard/Utility/DependencyOrderingUtility.cs
Normal file
41
src/Orchard/Utility/DependencyOrderingUtility.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Orchard.Utility {
|
||||
public static class DependencyOrdering {
|
||||
|
||||
class Linkage<T> {
|
||||
public T Element { get; set; }
|
||||
public bool Used { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort a collection of elements "by dependency order". By passing a lambda which determines if an element
|
||||
/// is a dependency of another, this algorithm will return the collection of elements sorted
|
||||
/// so that a given element in the sequence doesn't depend on any other element further in the sequence.
|
||||
/// </summary>
|
||||
public static IEnumerable<T> OrderByDependencies<T>(this IEnumerable<T> elements, Func<T, T, bool> hasDependency) {
|
||||
var population = elements.Select(d => new Linkage<T> {
|
||||
Element = d
|
||||
}).ToArray();
|
||||
|
||||
var result = new List<T>();
|
||||
foreach (var item in population) {
|
||||
Add(item, result, population, hasDependency);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void Add<T>(Linkage<T> item, ICollection<T> list, IEnumerable<Linkage<T>> population, Func<T, T, bool> hasDependency) {
|
||||
if (item.Used)
|
||||
return;
|
||||
|
||||
item.Used = true;
|
||||
foreach (var dependency in population.Where(dep => hasDependency(item.Element, dep.Element))) {
|
||||
Add(dependency, list, population, hasDependency);
|
||||
}
|
||||
list.Add(item.Element);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user