Skip to content

Commit d1a010d

Browse files
Added back ModuleDependencies tool
1 parent 908df56 commit d1a010d

File tree

12 files changed

+185
-208
lines changed

12 files changed

+185
-208
lines changed

DeveloperTools/Controllers/ModuleDependenciesController.cs

Lines changed: 0 additions & 127 deletions
This file was deleted.

tests/temp/ModuleDependencies/Index.cshtml renamed to DeveloperTools/EPiServer.DeveloperTools.Views/Views/ModuleDependencies/Index.cshtml

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,7 @@
11
@using Microsoft.AspNetCore.Html
2-
@using System.Collections
3-
@using DeveloperTools.Models
4-
@using EPiServer.Shell
52
@using Newtonsoft.Json
63
@using Newtonsoft.Json.Serialization
7-
@inherits System.Web.Mvc.WebViewPage<DeveloperTools.Models.ModuleDependencyViewModel>
8-
9-
@{
10-
ViewBag.SkipDojo = true;
11-
Layout = Paths.ToResource("EPiServer.DeveloperTools", "Views/Shared/DevToolsMaster.cshtml");
12-
}
13-
14-
@section Styles {
15-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis-network.min.css" integrity="sha256-tTIVWrgsLDcekkoaiqePYP86joMAiyp4KqEswPMmTfQ=" crossorigin="anonymous" />
16-
<style type="text/css">
17-
#graphContainer {
18-
margin: 0 auto;
19-
display: block;
20-
width: calc(100vw - 100px);
21-
height: calc(100vh - 200px);
22-
}
23-
24-
#modulesnetwork {
25-
width: 100%;
26-
height: 100%;
27-
}
28-
</style>
29-
}
4+
@model EPiServer.DeveloperTools.Features.ModuleDependencies.ModuleDependencyViewModel
305

316
<div class="epi-contentArea">
327
<h1 class="EP-prefix">Module Dependencies</h1>
@@ -61,11 +36,28 @@
6136
</div>
6237
</div>
6338

64-
@section Scripts {
39+
@section AdditionalStyles {
40+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis-network.min.css" integrity="sha256-tTIVWrgsLDcekkoaiqePYP86joMAiyp4KqEswPMmTfQ=" crossorigin="anonymous" />
41+
<style type="text/css">
42+
#graphContainer {
43+
margin: 0 auto;
44+
display: block;
45+
width: calc(100vw - 100px);
46+
height: calc(100vh - 200px);
47+
}
48+
49+
#modulesnetwork {
50+
width: 100%;
51+
height: 100%;
52+
}
53+
</style>
54+
}
55+
56+
@section AdditionalScripts {
6557
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js" integrity="sha256-JuQeAGbk9rG/EoRMixuy5X8syzICcvB0dj3KindZkY0=" crossorigin="anonymous"></script>
6658
<script type="text/javascript">
67-
var nodes = HtmlString.Create(JsonConvert.SerializeObject(Model.Nodes, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() })),
68-
edges = HtmlString.Create(JsonConvert.SerializeObject(Model.Links, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() })),
59+
var nodes = @(new HtmlString(JsonConvert.SerializeObject(Model.Nodes, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }))),
60+
edges = @(new HtmlString(JsonConvert.SerializeObject(Model.Links, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }))),
6961
network,
7062
allNodes,
7163
highlightActive = false;
@@ -215,3 +207,4 @@
215207
redrawAll();
216208
</script>
217209
}
210+

DeveloperTools/EPiServer.DeveloperTools.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@
4444
</None>
4545
</ItemGroup>
4646

47-
<ItemGroup>
48-
<Folder Include="EPiServer.DeveloperTools.Views\Views\StartupPerf\" />
49-
</ItemGroup>
50-
5147
<PropertyGroup>
5248
<PostBuildEvent>powershell.exe -noexit -file "$(ProjectDir)copy-to-sandbox.ps1"</PostBuildEvent>
5349
</PropertyGroup>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Reflection;
6+
using DeveloperTools.Models;
7+
using EPiServer.DeveloperTools.Features.Common;
8+
using EPiServer.Framework.Initialization;
9+
using EPiServer.ServiceLocation;
10+
using Microsoft.AspNetCore.Mvc;
11+
12+
namespace EPiServer.DeveloperTools.Features.ModuleDependencies;
13+
14+
public class ModuleDependenciesController : DeveloperToolsController
15+
{
16+
private readonly Dictionary<string, int> _assemblyGroups = new();
17+
private readonly IInitializationEngine _engine;
18+
19+
public ModuleDependenciesController(IInitializationEngine engine)
20+
{
21+
_engine = engine;
22+
}
23+
24+
public ActionResult Index(bool showAll = false)
25+
{
26+
var sortedModules = GetSortedModules();
27+
28+
var modules = from module in sortedModules
29+
let asmName = module.Type.Assembly.GetName().Name + ".dll"
30+
select new ModuleInfo
31+
{
32+
Id = module.Type.FullName,
33+
ModuleType = module.Type,
34+
Label = module.Type.Name,
35+
Title =
36+
$"Name: {module.Type.Name}<br>Type: {(typeof(IConfigurableModule).IsAssignableFrom(module.Type) ? "Configurable" : "Initializable")}<br>Namespace: {module.Type.Namespace}<br>Assembly: {asmName}",
37+
Group = GetAssemblyGroup(asmName)
38+
};
39+
40+
var dependencies = sortedModules.Where(_ => _.Dependencies.Count > 0)
41+
.SelectMany(_ => _.Dependencies,
42+
(from, to) => new ModuleDependency { From = from.Type.FullName, To = to.FullName });
43+
44+
if (!showAll)
45+
{
46+
dependencies = dependencies.Where(_ => !_.From.StartsWith("EPiServer"));
47+
modules = modules.Where(m => !m.ModuleType.FullName.StartsWith("EPiServer"))
48+
.Union(modules.Where(m => dependencies.Any(d => d.To == m.ModuleType.FullName)))
49+
.DistinctBy(_ => _.Id)
50+
.ToList();
51+
}
52+
53+
var model = new ModuleDependencyViewModel { Nodes = modules.ToList(), Links = dependencies.ToList(), ShowAll = showAll };
54+
55+
WeightModulesByDependants(model);
56+
57+
return View(model);
58+
}
59+
60+
private void WeightModulesByDependants(ModuleDependencyViewModel model)
61+
{
62+
// process sizes of the modules
63+
var incomingDeps = model.Links.GroupBy(_ => _.To)
64+
.Select(group => new { Name = group.Key, Count = group.Count() });
65+
66+
foreach (var incomingDep in incomingDeps)
67+
{
68+
var m = model.Nodes.First(_ => _.Id == incomingDep.Name);
69+
m.Size = m.Size + incomingDep.Count * 2;
70+
}
71+
}
72+
73+
private List<ExtractedModuleInfo> GetSortedModules()
74+
{
75+
var sortedModules =
76+
_engine.GetType()
77+
.GetField("_dependencySortedList", BindingFlags.NonPublic | BindingFlags.Instance)
78+
.GetValue(_engine) as IList;
79+
var result = new List<ExtractedModuleInfo>();
80+
81+
// some nasty dirty internal business to get sorted module list with dependencies
82+
foreach (var module in sortedModules)
83+
{
84+
var t = module.GetType();
85+
86+
// we cannot cast to `ModuleNode` as this is internal type. we have to blindly invoke property from the underlying type
87+
var moduleType = t.GetProperty("ModuleType", BindingFlags.Instance | BindingFlags.Public).GetValue(module) as Type;
88+
var dependencies =
89+
t.GetProperty("Dependencies", BindingFlags.Instance | BindingFlags.Public).GetValue(module) as IEnumerable;
90+
91+
var dependencyTypes = from object dep in dependencies
92+
select dep as Type;
93+
94+
result.Add(new ExtractedModuleInfo { Type = moduleType, Dependencies = dependencyTypes.ToList() });
95+
}
96+
97+
return result;
98+
}
99+
100+
private int GetAssemblyGroup(string assemblyName)
101+
{
102+
if (!_assemblyGroups.Any())
103+
{
104+
_assemblyGroups.Add(assemblyName, 1);
105+
return 1;
106+
}
107+
108+
if (_assemblyGroups.ContainsKey(assemblyName))
109+
{
110+
return _assemblyGroups[assemblyName];
111+
}
112+
113+
var max = _assemblyGroups.Max(_ => _.Value);
114+
_assemblyGroups.Add(assemblyName, max + 1);
115+
116+
return max;
117+
}
118+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace EPiServer.DeveloperTools.Features.ModuleDependencies;
2+
3+
public class ModuleDependency
4+
{
5+
public string From { get; set; }
6+
7+
public string To { get; set; }
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Collections.Generic;
2+
3+
namespace EPiServer.DeveloperTools.Features.ModuleDependencies;
4+
5+
public class ModuleDependencyViewModel
6+
{
7+
public ICollection<ModuleInfo> Nodes { get; set; }
8+
9+
public ICollection<ModuleDependency> Links { get; set; }
10+
11+
public bool ShowAll { get; set; }
12+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace EPiServer.DeveloperTools.Features.ModuleDependencies;
4+
5+
public class ModuleInfo
6+
{
7+
public ModuleInfo()
8+
{
9+
Size = 10;
10+
}
11+
12+
public string Id { get; set; }
13+
14+
public int Group { get; set; }
15+
16+
public int Size { get; set; }
17+
18+
public Type ModuleType { get; set; }
19+
20+
public string Label { get; set; }
21+
22+
public string Title { get; set; }
23+
}

DeveloperTools/MenuProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public IEnumerable<MenuItem> GetMenuItems()
3636
CreateUrlMenuItem("Remote Events", "RemoteEvent", 100),
3737
CreateUrlMenuItem("Routes", "Routes", 110),
3838
CreateUrlMenuItem("View Locations", "ViewLocations", 120),
39-
//CreateUrlMenuItem("Module Dependencies", "ModuleDependencies", 130),
39+
CreateUrlMenuItem("Module Dependencies", "ModuleDependencies", 130),
4040
CreateUrlMenuItem("Local Object Cache", "LocalObjectCache", 140)
4141
};
4242
}

DeveloperTools/Models/ModuleDependency.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)