/
ProjectTypeHandler.cs
153 lines (130 loc) · 4.75 KB
/
ProjectTypeHandler.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
namespace JMS.Tools.SolutionUpdater
{
/// <summary>
/// Beschreibt die Verwaltung einer Art von Projekt.
/// </summary>
public abstract class ProjectTypeHandler
{
/// <summary>
/// Die Rohdaten.
/// </summary>
protected readonly XmlDocument Document = new XmlDocument();
/// <summary>
/// Der zu verwendende Namensraum.
/// </summary>
protected readonly XmlNamespaceManager Namespaces;
/// <summary>
/// Der volle Pfad zur Projektdatei.
/// </summary>
public FileInfo FilePath { get; private set; }
/// <summary>
/// Der XPath zum Namen der Assembly.
/// </summary>
protected abstract string TargetNamePath { get; }
/// <summary>
/// Der Name der Zieldatei.
/// </summary>
public string AssemblyName { get; private set; }
/// <summary>
/// Die Liste aller Abhängigkeiten.
/// </summary>
public HashSet<Guid> Dependencies { get; private set; }
/// <summary>
/// Die Liste aller Abhängigkeiten, iterativ aufgelöst.
/// </summary>
public HashSet<Guid> DeepDependencies { get; private set; }
/// <summary>
/// Initialisiert eine Verwaltung.
/// </summary>
/// <param name="path">Der volle Pfad zur Projektdatei.</param>
protected ProjectTypeHandler( FileInfo path = null )
{
// Remember
FilePath = path;
// Attach to the table
Namespaces = new XmlNamespaceManager( Document.NameTable );
// Create the default name space
Namespaces.AddNamespace( "msbuild", "http://schemas.microsoft.com/developer/msbuild/2003" );
// None
if (path == null)
{
// Fake name
AssemblyName = Guid.NewGuid().ToString( "N" ).ToUpper();
// Done
return;
}
// Load
Document.Load( FilePath.FullName );
// Read the name of the target
var assemblyName = Document.SelectSingleNode( TargetNamePath, Namespaces );
if (assemblyName != null)
AssemblyName = assemblyName.InnerText;
// Validate
if (string.IsNullOrEmpty( AssemblyName ))
AssemblyName = Path.GetFileNameWithoutExtension( path.FullName );
}
/// <summary>
/// Ermittelt alle Referenzen.
/// </summary>
protected virtual IEnumerable<string> References
{
get
{
// Process
return
Document
.SelectNodes( "msbuild:Project/msbuild:ItemGroup/msbuild:Reference[@Include]", Namespaces )
.Cast<XmlElement>()
.Select( element => new AssemblyName( element.GetAttribute( "Include" ) ) )
.Select( name => name.Name );
}
}
/// <summary>
/// Löst alle Referenzen auf.
/// </summary>
/// <param name="projects">Alle bekannten Projekte.</param>
public void Resolve( Dictionary<string, ProjectSection> projects )
{
// Create new
Dependencies = new HashSet<Guid>();
// Load references
foreach (var reference in References)
{
// Look it up
ProjectSection project;
if (projects.TryGetValue( reference, out project ))
Dependencies.Add( project.UniqueIdentifier );
}
}
/// <summary>
/// Löst alle Referenzen in die Tiefe auf.
/// </summary>
/// <param name="projectLookup">Die Liste aller Projekte.</param>
/// <returns>Die iterativ aufgelöste Liste der Abhängigkeiten.</returns>
public IEnumerable<Guid> DeepResolve( Dictionary<Guid, ProjectSection> projectLookup )
{
// Create once
if (DeepDependencies == null)
{
// Initial direct
DeepDependencies = new HashSet<Guid>( Dependencies );
// Resolve all
foreach (var projectIdentifier in Dependencies)
{
// Do the resolve
var dependencies = projectLookup[projectIdentifier].GetDeepDependencies( projectLookup );
// Merge with us
DeepDependencies.UnionWith( dependencies );
}
}
// Report
return DeepDependencies;
}
}
}