-
Notifications
You must be signed in to change notification settings - Fork 396
Expand file tree
/
Copy pathBaseWrapperNode.cs
More file actions
112 lines (94 loc) · 2.79 KB
/
BaseWrapperNode.cs
File metadata and controls
112 lines (94 loc) · 2.79 KB
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
using System;
namespace ReClassNET.Nodes
{
public abstract class BaseWrapperNode : BaseNode
{
/// <summary>Gets or sets the inner node.</summary>
public BaseNode InnerNode { get; private set; }
/// <summary>Gets signaled if the inner node was changed.</summary>
public event NodeEventHandler InnerNodeChanged;
/// <summary>True to perform class cycle checks when changing the inner node.</summary>
protected abstract bool PerformCycleCheck { get; }
/// <summary>
/// Should be called before <see cref="ChangeInnerNode"/> to test if the node can handle the inner node type.
/// </summary>
/// <param name="node">The new inner node type.</param>
/// <returns>True if the class can handle the inner node type or false otherwise.</returns>
public abstract bool CanChangeInnerNodeTo(BaseNode node);
/// <summary>Changes the inner node.</summary>
/// <param name="node">The new node.</param>
public void ChangeInnerNode(BaseNode node)
{
if (!CanChangeInnerNodeTo(node))
{
throw new InvalidOperationException($"Can't change inner node to '{node?.GetType().ToString() ?? "null"}'");
}
if (InnerNode != node)
{
InnerNode = node;
if (node != null)
{
node.ParentNode = this;
}
InnerNodeChanged?.Invoke(this);
GetParentContainer()?.ChildHasChanged(this);
}
}
/// <summary>
/// Resolve the most inner node of a <see cref="BaseWrapperNode"/> chain.
/// </summary>
/// <returns>The most inner node or null.</returns>
public BaseNode ResolveMostInnerNode()
{
if (InnerNode == null)
{
return null;
}
if (InnerNode is BaseWrapperNode baseWrapperNode)
{
return baseWrapperNode.ResolveMostInnerNode();
}
return InnerNode;
}
/// <summary>
/// Tests if the cycle check is really needed in a <see cref="BaseWrapperNode"/> chain.
/// </summary>
/// <returns></returns>
public bool ShouldPerformCycleCheckForInnerNode()
{
// TODO Should there be a "is ClassNode" for the last inner node?
if (!PerformCycleCheck)
{
return false;
}
var wrapperNode = this;
while (wrapperNode.InnerNode is BaseWrapperNode wrappedNode)
{
if (!wrappedNode.PerformCycleCheck)
{
return false;
}
wrapperNode = wrappedNode;
}
return true;
}
/// <summary>
/// Tests if the given node type is present in the chain of wrapped nodes.
/// </summary>
/// <typeparam name="TNode">The node type to check.</typeparam>
/// <returns>True if the given node type is present in the chain of wrapped nodes, false otherwise.</returns>
public bool IsNodePresentInChain<TNode>() where TNode : BaseNode
{
BaseNode node = this;
while (node is BaseWrapperNode wrapperNode)
{
if (node is TNode)
{
return true;
}
node = wrapperNode.InnerNode;
}
return false;
}
}
}