Skip to content

Commit 79d533b

Browse files
committed
修复循环依赖StackOverflow问题
1 parent d964a35 commit 79d533b

3 files changed

Lines changed: 56 additions & 32 deletions

File tree

src/Riven.Modular/Modular/ModuleDescriptor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,10 @@ public ModuleDescriptor(Type moduleType, params IModuleDescriptor[] dependencies
2929
this.ModuleType = moduleType;
3030
this.Dependencies = dependencies ?? new ModuleDescriptor[0];
3131
}
32+
33+
public override string ToString()
34+
{
35+
return ModuleType.FullName;
36+
}
3237
}
3338
}

src/Riven.Modular/Modular/ModuleManager.cs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,37 +162,54 @@ public virtual List<IModuleDescriptor> ModuleSort<TModule>(List<IModuleDescripto
162162
/// </summary>
163163
/// <param name="moduleType"></param>
164164
/// <returns></returns>
165-
protected virtual List<IModuleDescriptor> VisitModule(Type moduleType)
165+
protected virtual List<IModuleDescriptor> VisitModule(Type moduleType, Type parentModuleType = null, Dictionary<Type, bool> parentDependModuleType = null)
166166
{
167167
var moduleDescriptors = new List<IModuleDescriptor>();
168168
if (!moduleType.IsModule())
169169
{
170-
return moduleDescriptors;
170+
goto end;
171+
}
172+
if (parentDependModuleType == null)
173+
{
174+
parentDependModuleType = new Dictionary<Type, bool>();
171175
}
172176

173-
// 依赖标记
177+
// 获取依赖模块信息
174178
var dependModulesAttribute = moduleType.GetCustomAttribute<DependsOnAttribute>(false);
175179

176-
// 依赖属性为空
180+
// 创建模块信息
181+
// 依赖模块为空
177182
if (dependModulesAttribute == null)
178183
{
179-
moduleDescriptors.Add(new ModuleDescriptor(moduleType));
184+
moduleDescriptors.Add(
185+
new ModuleDescriptor(moduleType)
186+
);
187+
goto end;
180188
}
181-
else
189+
190+
// 依赖属性不为空,递归获取依赖
191+
var dependModuleDescriptors = new List<IModuleDescriptor>();
192+
foreach (var dependModuleType in dependModulesAttribute.DependModuleTypes)
182193
{
183-
// 依赖属性不为空,递归获取依赖
184-
var dependModuleDescriptors = new List<IModuleDescriptor>();
185-
foreach (var dependModuleType in dependModulesAttribute.DependModuleTypes)
194+
if (parentDependModuleType.TryGetValue(dependModuleType, out var isEx) || dependModuleType == parentModuleType)
186195
{
187-
dependModuleDescriptors.AddRange(
188-
this.VisitModule(dependModuleType)
189-
);
196+
throw new InvalidOperationException($"There are cyclic dependencies!\r\n{moduleType.FullName} <--> {dependModuleType.FullName}");
190197
}
191198

192-
// 创建模块描述信息,内容为模块类型和依赖类型
193-
moduleDescriptors.Add(new ModuleDescriptor(moduleType, dependModuleDescriptors.ToArray()));
199+
parentDependModuleType.Add(dependModuleType, true);
200+
dependModuleDescriptors.AddRange(
201+
this.VisitModule(dependModuleType, moduleType, parentDependModuleType)
202+
);
194203
}
195204

205+
parentDependModuleType.Clear();
206+
// 创建模块信息,内容为模块类型和依赖信息
207+
moduleDescriptors.Add(
208+
new ModuleDescriptor(moduleType, dependModuleDescriptors.ToArray())
209+
);
210+
211+
212+
end: // 返回结果
196213
return moduleDescriptors;
197214
}
198215

src/Riven.Modular/Modular/Topological.cs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,30 +51,32 @@ static void Visit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> so
5151
// 如果处理的为当前节点,则说明存在循环引用
5252
if (inProcess)
5353
{
54-
throw new ArgumentException("topological module cyclic dependency found.");
54+
throw new InvalidOperationException($"There are cyclic dependencies!\r\n{item.ToString()}");
5555
}
56+
57+
return;
5658
}
57-
else
58-
{
59-
// 正在处理当前顶点
60-
visited[item] = true;
6159

62-
// 获得所有依赖项
63-
var dependencies = getDependencies(item);
64-
// 如果依赖项集合不为空,遍历访问其依赖节点
65-
if (dependencies != null)
60+
61+
62+
// 正在处理当前顶点
63+
visited[item] = true;
64+
65+
// 获得所有依赖项
66+
var dependencies = getDependencies(item);
67+
// 如果依赖项集合不为空,遍历访问其依赖节点
68+
if (dependencies != null)
69+
{
70+
foreach (var dependency in dependencies)
6671
{
67-
foreach (var dependency in dependencies)
68-
{
69-
// 递归遍历访问
70-
Visit(dependency, getDependencies, sorted, visited);
71-
}
72+
// 递归遍历访问
73+
Visit(dependency, getDependencies, sorted, visited);
7274
}
73-
74-
// 处理完成置为 false
75-
visited[item] = false;
76-
sorted.Add(item);
7775
}
76+
77+
// 处理完成置为 false
78+
visited[item] = false;
79+
sorted.Add(item);
7880
}
7981
}
8082
}

0 commit comments

Comments
 (0)