-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDotNetContainerExtensions.cs
More file actions
132 lines (105 loc) · 6.21 KB
/
DotNetContainerExtensions.cs
File metadata and controls
132 lines (105 loc) · 6.21 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//*****************************************************************************
//* Code Factory SDK
//* Copyright (c) 2020 CodeFactory, LLC
//*****************************************************************************
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace CodeFactory.DotNet
{
/// <summary>
/// Extension management class that manages dot net models that implement the <see cref="IDotNetContainer"/> interface.
/// </summary>
public static class DotNetContainerExtensions
{
/// <summary>
/// Loads all members from a target model that implements <see cref="IDotNetContainer"/> and returns all members and the comparison hash code for each member.
/// </summary>
/// <param name="source">The target container to load members from.</param>
/// <param name="comparisonType">The type of hash code to build for comparision. Default comparison type is set to the base comparison. </param>
/// <returns>List of all the hash codes and the members for each hashcode.</returns>
/// <exception cref="ArgumentNullException">Thrown if the source container is null.</exception>
public static IReadOnlyList<KeyValuePair<int, IDotNetMember>> FormatCSharpComparisonMembers(
this IDotNetContainer source, MemberComparisonType comparisonType = MemberComparisonType.Base)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (!source.Members.Any()) return ImmutableList<KeyValuePair<int, IDotNetMember>>.Empty;
List<KeyValuePair<int, IDotNetMember>> result = new List<KeyValuePair<int, IDotNetMember>>();
var members = source.Members.Select(m =>
new KeyValuePair<int, IDotNetMember>(m.FormatCSharpMemberComparisonHashCode(comparisonType), m));
result.AddRange(members);
switch (source.ContainerType)
{
case DotNetContainerType.Interface:
var interfaceContainer = source as IDotNetInterface;
if (interfaceContainer?.InheritedInterfaces != null)
{
foreach (var inheritedInterface in interfaceContainer.InheritedInterfaces)
{
var interfaceMembers = inheritedInterface.FormatCSharpComparisonMembers(comparisonType);
if (interfaceMembers.Any()) result.AddRange(interfaceMembers);
}
}
break;
case DotNetContainerType.Class:
var classContainer = source as IDotNetClass;
if (classContainer?.BaseClass != null)
{
var baseMembers = classContainer.BaseClass.FormatCSharpComparisonMembers(comparisonType);
if (baseMembers.Any()) result.AddRange(baseMembers);
}
break;
}
return result.ToImmutableArray();
}
/// <summary>
/// Creates a list of the interface members that are not implemented in the <see cref="IDotNetClass"/> model.
/// </summary>
/// <param name="source">The source model to check.</param>
/// <returns>List of models that are missing or an empty list if there are no missing members.</returns>
/// <exception cref="ArgumentNullException">Throws an argument null exception if the model does not exist.</exception>
public static IReadOnlyList<IDotNetMember> MissingInterfaceMembers(this IDotNetClass source)
{
return MissingContainerInterfaceMembers(source);
}
/// <summary>
/// Creates a list of the interface members that are not implemented in the <see cref="IDotNetStructure"/> model.
/// </summary>
/// <param name="source">The source model to check.</param>
/// <returns>List of models that are missing or an empty list if there are no missing members.</returns>
/// <exception cref="ArgumentNullException">Throws an argument null exception if the model does not exist.</exception>
public static IReadOnlyList<IDotNetMember> MissingInterfaceMembers(this IDotNetStructure source)
{
return MissingContainerInterfaceMembers(source);
}
/// <summary>
/// Creates a list of the interface members that are not implemented in the <see cref="IDotNetContainer"/> model.
/// </summary>
/// <param name="source">The source model to check.</param>
/// <returns>List of models that are missing or an empty list if there are no missing members.</returns>
/// <exception cref="ArgumentNullException">Throws an argument null exception if the model does not exist.</exception>
private static IReadOnlyList<IDotNetMember> MissingContainerInterfaceMembers(IDotNetContainer source)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (source.ContainerType == DotNetContainerType.Interface) return ImmutableList<IDotNetMember>.Empty;
if (source.InheritedInterfaces == null) return ImmutableList<IDotNetMember>.Empty;
var sourceMembers = source.FormatCSharpComparisonMembers(MemberComparisonType.Security);
var interfaceMembers = new Dictionary<int, IDotNetMember>();
foreach (var inheritedInterface in source.InheritedInterfaces)
{
var compareMembers = inheritedInterface.FormatCSharpComparisonMembers(MemberComparisonType.Security);
if (!compareMembers.Any()) continue;
foreach (var compareMember in compareMembers)
{
if (!interfaceMembers.ContainsKey(compareMember.Key))
interfaceMembers.Add(compareMember.Key, compareMember.Value);
}
}
if (!interfaceMembers.Any()) return ImmutableList<IDotNetMember>.Empty;
return (from interfaceMember in interfaceMembers
where !sourceMembers.Any(m => m.Key == interfaceMember.Key)
select interfaceMember.Value).ToImmutableList();
}
}
}