-
-
Notifications
You must be signed in to change notification settings - Fork 229
/
TypeNodeBuilder.cs
119 lines (107 loc) · 3.47 KB
/
TypeNodeBuilder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Mono.Cecil;
public partial class ModuleWeaver
{
List<TypeDefinition> allClasses;
public List<TypeNode> Nodes;
public List<TypeNode> NotifyNodes;
public void BuildTypeNodes()
{
// setup a filter delegate to apply the namespace filters
Func<TypeDefinition, bool> extraFilter =
t => !NamespaceFilters.Any() || NamespaceFilters.Any(filter => Regex.IsMatch(t.FullName, filter));
allClasses = ModuleDefinition
.GetTypes()
.Where(x => x.IsClass && x.BaseType != null)
.Where(extraFilter)
.ToList();
Nodes = new List<TypeNode>();
NotifyNodes = new List<TypeNode>();
TypeDefinition typeDefinition;
while ((typeDefinition = allClasses.FirstOrDefault()) != null)
{
AddClass(typeDefinition);
}
PopulateINotifyNodes(Nodes);
foreach (var notifyNode in NotifyNodes)
{
Nodes.Remove(notifyNode);
}
PopulateInjectedINotifyNodes(Nodes);
}
void PopulateINotifyNodes(List<TypeNode> typeNodes)
{
foreach (var node in typeNodes)
{
if (HierarchyImplementsINotify(node.TypeDefinition))
{
NotifyNodes.Add(node);
continue;
}
PopulateINotifyNodes(node.Nodes);
}
}
void PopulateInjectedINotifyNodes(List<TypeNode> typeNodes)
{
foreach (var node in typeNodes)
{
if (HasNotifyPropertyChangedAttribute(node.TypeDefinition))
{
if (HierarchyImplementsINotify(node.TypeDefinition))
{
throw new WeavingException($"The type '{node.TypeDefinition.FullName}' already implements INotifyPropertyChanged so [AddINotifyPropertyChangedInterfaceAttribute] is redundant.");
}
InjectINotifyPropertyChangedInterface(node.TypeDefinition);
NotifyNodes.Add(node);
continue;
}
PopulateInjectedINotifyNodes(node.Nodes);
}
}
static bool HasNotifyPropertyChangedAttribute(TypeDefinition typeDefinition)
{
return typeDefinition.CustomAttributes.ContainsAttribute("PropertyChanged.AddINotifyPropertyChangedInterfaceAttribute");
}
TypeNode AddClass(TypeDefinition typeDefinition)
{
allClasses.Remove(typeDefinition);
var typeNode = new TypeNode
{
TypeDefinition = typeDefinition
};
if (typeDefinition.BaseType.Scope.Name != ModuleDefinition.Name)
{
Nodes.Add(typeNode);
}
else
{
var baseType = Resolve(typeDefinition.BaseType);
var parentNode = FindClassNode(baseType, Nodes);
if (parentNode == null)
{
parentNode = AddClass(baseType);
}
parentNode.Nodes.Add(typeNode);
}
return typeNode;
}
TypeNode FindClassNode(TypeDefinition type, IEnumerable<TypeNode> typeNode)
{
foreach (var node in typeNode)
{
if (type == node.TypeDefinition)
{
return node;
}
var findNode = FindClassNode(type, node.Nodes);
if (findNode != null)
{
return findNode;
}
}
return null;
}
}