-
Notifications
You must be signed in to change notification settings - Fork 5
/
ModelElementBase.cs
132 lines (116 loc) · 4.91 KB
/
ModelElementBase.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
120
121
122
123
124
125
126
127
128
129
130
131
132
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ModelElementBase.cs" company="Kephas Software SRL">
// Copyright (c) Kephas Software SRL. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
// </copyright>
// <summary>
// Base abstract class for model elements.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Kephas.Model.Elements
{
using System.Collections.Generic;
using System.Linq;
using Kephas.Model.Configuration;
using Kephas.Model.Construction;
using Kephas.Model.Construction.Internal;
/// <summary>
/// Base abstract class for model elements.
/// </summary>
/// <typeparam name="TModelContract">The type of the model contract (the model interface).</typeparam>
public abstract class ModelElementBase<TModelContract> : NamedElementBase<TModelContract>, IModelElement
where TModelContract : IModelElement
{
/// <summary>
/// The members.
/// </summary>
private readonly Dictionary<string, INamedElement> members = new Dictionary<string, INamedElement>();
/// <summary>
/// The member counter.
/// </summary>
private int memberCounter = 0;
/// <summary>
/// Initializes a new instance of the <see cref="ModelElementBase{TModelContract}"/> class.
/// </summary>
/// <param name="constructionContext">Context for the construction.</param>
/// <param name="name">The name.</param>
protected ModelElementBase(IModelConstructionContext constructionContext, string name)
: base(constructionContext, name)
{
}
/// <summary>
/// Gets the members of this model element.
/// </summary>
/// <value>
/// The model element members.
/// </value>
public virtual IEnumerable<INamedElement> Members => this.members.Values;
/// <summary>
/// Gets the element annotations.
/// </summary>
/// <value>
/// The element annotations.
/// </value>
public override IEnumerable<IAnnotation> Annotations => this.Members.OfType<IAnnotation>();
/// <summary>
/// Gets the member with the specified qualified name.
/// </summary>
/// <param name="qualifiedName">The qualified name of the member.</param>
/// <param name="throwOnNotFound">If set to <c>true</c> and the member is not found, an exception occurs; otherwise <c>null</c> is returned if the member is not found.</param>
/// <returns>
/// The member with the provided qualified name or <c>null</c>.
/// </returns>
public virtual INamedElement? GetMember(string qualifiedName, bool throwOnNotFound = true)
{
if (this.members.TryGetValue(qualifiedName, out var element))
{
return element;
}
if (throwOnNotFound)
{
throw new ElementNotFoundException(qualifiedName, this.Name);
}
return null;
}
/// <summary>
/// Adds the member to the members list.
/// </summary>
/// <param name="member">The member.</param>
protected override void AddMember(INamedElement member)
{
if (member.DeclaringContainer == null)
{
var memberBuilder = member as IConstructibleElement;
memberBuilder?.SetDeclaringContainer(this);
}
if (this.members.ContainsKey(member.Name))
{
this.members.Add($"{member.Name}_{this.memberCounter++}", member);
}
else
{
this.members.Add(member.Name, member);
}
}
/// <summary>
/// Called when the construction is complete.
/// </summary>
/// <param name="constructionContext">Context for the construction.</param>
protected override void OnCompleteConstruction(IModelConstructionContext constructionContext)
{
var declaredMembers = ((IModelElement)this).GetDeclaredMembers();
// invoke all members which are element configurators
var configurators = declaredMembers.OfType<IElementConfigurator>().ToList();
foreach (var configurator in configurators)
{
configurator.Configure(constructionContext, this);
}
// Complete construction for declared members
foreach (var declaredMember in declaredMembers)
{
(declaredMember as IConstructibleElement)?.CompleteConstruction(constructionContext);
}
base.OnCompleteConstruction(constructionContext);
}
}
}