Support tuples from extensions and make SourcePath a path instead of string
Rob Mensching committed
Dec 2, 2017 at 00:44 UTC
53e877183abe0dbbb623c39380101bc369e9f265
13 files changed
+371
-77
WixToolset.Data.sln
+19
-1
@@ -1,10 +1,12 @@
1
2
Microsoft Visual Studio Solution File, Format Version 12.00
3
# Visual Studio 15
4
-VisualStudioVersion = 15.0.26730.0
4
+VisualStudioVersion = 15.0.27004.2009
5
MinimumVisualStudioVersion = 10.0.40219.1
6
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Data", "src\WixToolset.Data\WixToolset.Data.csproj", "{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}"
7
EndProject
8
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Data", "src\test\WixToolsetTest.Data\WixToolsetTest.Data.csproj", "{6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}"
9
+EndProject
10
Global
11
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12
Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,22 @@ Global
35
{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x64.Build.0 = Release|Any CPU
36
{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.ActiveCfg = Release|Any CPU
37
{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.Build.0 = Release|Any CPU
38
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
40
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|arm.ActiveCfg = Debug|Any CPU
41
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|arm.Build.0 = Debug|Any CPU
42
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.ActiveCfg = Debug|Any CPU
43
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.Build.0 = Debug|Any CPU
44
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.ActiveCfg = Debug|Any CPU
45
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.Build.0 = Debug|Any CPU
46
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
47
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.Build.0 = Release|Any CPU
48
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|arm.ActiveCfg = Release|Any CPU
49
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|arm.Build.0 = Release|Any CPU
50
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.ActiveCfg = Release|Any CPU
51
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.Build.0 = Release|Any CPU
52
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x86.ActiveCfg = Release|Any CPU
53
+ {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x86.Build.0 = Release|Any CPU
54
EndGlobalSection
55
GlobalSection(SolutionProperties) = preSolution
56
HideSolutionNode = FALSE
src/Directory.Build.props
+3
-1
@@ -5,11 +5,13 @@
5
<PropertyGroup>
6
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
7
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)..\build\obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
8
- <OutputPath>$(MSBuildThisFileDirectory)..\build\$(Configuration)\</OutputPath>
8
+ <BaseOutputPath>$(MSBuildThisFileDirectory)..\build\$(Configuration)\</BaseOutputPath>
9
+ <OutputPath>$(BaseOutputPath)</OutputPath>
10
11
<Authors>WiX Toolset Team</Authors>
12
<Company>WiX Toolset</Company>
13
<Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
14
+ <Product>WiX Toolset</Product>
15
</PropertyGroup>
16
17
<PropertyGroup>
src/WixToolset.Data/DictionaryExtensions.cs
new
+14
@@ -0,0 +1,14 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Data
4
+{
5
+ using System.Collections.Generic;
6
+
7
+ internal static class DictionaryExtensions
8
+ {
9
+ public static V GetValueOrDefault<K, V>(this IDictionary<K, V> dictionary, K key, V defaultValue = default(V))
10
+ {
11
+ return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
12
+ }
13
+ }
14
+}
src/WixToolset.Data/ITupleDefinitionCreator.cs
+2
@@ -4,6 +4,8 @@ namespace WixToolset.Data
4
{
5
public interface ITupleDefinitionCreator
6
{
7
+ void AddCustomTupleDefinition(IntermediateTupleDefinition definition);
8
+
9
bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition);
10
}
11
}
src/WixToolset.Data/Intermediate.cs
+127
-43
@@ -4,6 +4,7 @@ namespace WixToolset.Data
4
{
5
using System;
6
using System.Collections.Generic;
7
+ using System.Linq;
8
using System.IO;
9
using SimpleJson;
10
@@ -95,9 +96,24 @@ namespace WixToolset.Data
96
/// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
97
/// <returns>Returns the loaded intermediate.</returns>
98
public static Intermediate Load(string path, bool suppressVersionCheck = false)
99
+ {
100
+ using (var stream = File.OpenRead(path))
101
+ {
102
+ var creator = new SimpleTupleDefinitionCreator();
103
+ return Intermediate.Load(stream, path, creator, suppressVersionCheck);
104
+ }
105
+ }
106
+
107
+ /// <summary>
108
+ /// Loads an intermediate from a stream.
109
+ /// </summary>
110
+ /// <param name="stream">Stream to intermediate file.</param>
111
+ /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
112
+ /// <returns>Returns the loaded intermediate.</returns>
113
+ public static Intermediate Load(Stream stream, bool suppressVersionCheck = false)
114
{
115
var creator = new SimpleTupleDefinitionCreator();
100
- return Intermediate.Load(path, creator, suppressVersionCheck);
116
+ return Intermediate.Load(stream, creator, suppressVersionCheck);
117
}
118
119
/// <summary>
@@ -109,51 +125,22 @@ namespace WixToolset.Data
125
/// <returns>Returns the loaded intermediate.</returns>
126
public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
127
{
112
- JsonObject jsonObject;
113
-
114
- using (FileStream stream = File.OpenRead(path))
115
- using (FileStructure fs = FileStructure.Read(stream))
116
- {
117
- if (FileFormat.WixIR != fs.FileFormat)
118
- {
119
- throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat);
120
- }
121
-
122
- var json = fs.GetData();
123
- jsonObject = SimpleJson.DeserializeObject(json) as JsonObject;
124
- }
125
-
126
- if (!suppressVersionCheck)
128
+ using (var stream = File.OpenRead(path))
129
{
128
- var versionJson = jsonObject.GetValueOrDefault<string>("version");
129
-
130
- if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version))
131
- {
132
- throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
133
- }
130
+ return Intermediate.Load(stream, path, creator, suppressVersionCheck);
131
}
132
+ }
133
136
- var id = jsonObject.GetValueOrDefault<string>("id");
137
-
138
- var sections = new List<IntermediateSection>();
139
-
140
- var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections");
141
- foreach (JsonObject sectionJson in sectionsJson)
142
- {
143
- var section = IntermediateSection.Deserialize(creator, sectionJson);
144
- sections.Add(section);
145
- }
146
-
147
- var localizations = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase);
148
-
149
- //var localizationsJson = jsonObject.GetValueOrDefault<JsonArray>("localizations") ?? new JsonArray();
150
- //foreach (JsonObject localizationJson in localizationsJson)
151
- //{
152
- // var localization = Localization.Deserialize(localizationJson);
153
- // localizations.Add(localization.Culture, localization);
154
- //}
155
-
156
- return new Intermediate(id, sections, localizations, null);
134
+ /// <summary>
135
+ /// Loads an intermediate from a path on disk.
136
+ /// </summary>
137
+ /// <param name="stream">Stream to intermediate file.</param>
138
+ /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
139
+ /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
140
+ /// <returns>Returns the loaded intermediate.</returns>
141
+ public static Intermediate Load(Stream stream, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
142
+ {
143
+ return Load(stream, "<unknown>", creator, suppressVersionCheck);
144
}
145
146
/// <summary>
@@ -183,6 +170,21 @@ namespace WixToolset.Data
170
171
jsonObject.Add("sections", sectionsJson);
172
173
+ var customDefinitions = GetCustomDefinitionsInSections();
174
+
175
+ if (customDefinitions.Count > 0)
176
+ {
177
+ var customDefinitionsJson = new JsonArray(customDefinitions.Count);
178
+
179
+ foreach (var kvp in customDefinitions.OrderBy(d => d.Key))
180
+ {
181
+ var customDefinitionJson = kvp.Value.Serialize();
182
+ customDefinitionsJson.Add(customDefinitionJson);
183
+ }
184
+
185
+ jsonObject.Add("definitions", customDefinitionsJson);
186
+ }
187
+
188
//if (this.Localizations.Any())
189
//{
190
// var localizationsJson = new JsonArray();
@@ -200,6 +202,73 @@ namespace WixToolset.Data
202
}
203
}
204
205
+ /// <summary>
206
+ /// Loads an intermediate from a path on disk.
207
+ /// </summary>
208
+ /// <param name="stream">Stream to intermediate file.</param>
209
+ /// <param name="path">Path name of intermediate file.</param>
210
+ /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
211
+ /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
212
+ /// <returns>Returns the loaded intermediate.</returns>
213
+ internal static Intermediate Load(Stream stream, string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
214
+ {
215
+ JsonObject jsonObject;
216
+
217
+ using (var fs = FileStructure.Read(stream))
218
+ {
219
+ if (FileFormat.WixIR != fs.FileFormat)
220
+ {
221
+ throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat);
222
+ }
223
+
224
+ var json = fs.GetData();
225
+ jsonObject = SimpleJson.DeserializeObject(json) as JsonObject;
226
+ }
227
+
228
+ if (!suppressVersionCheck)
229
+ {
230
+ var versionJson = jsonObject.GetValueOrDefault<string>("version");
231
+
232
+ if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version))
233
+ {
234
+ throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
235
+ }
236
+ }
237
+
238
+ var definitionsJson = jsonObject.GetValueOrDefault<JsonArray>("definitions");
239
+
240
+ if (definitionsJson != null)
241
+ {
242
+ foreach (JsonObject definitionJson in definitionsJson)
243
+ {
244
+ var definition = IntermediateTupleDefinition.Deserialize(definitionJson);
245
+ creator.AddCustomTupleDefinition(definition);
246
+ }
247
+ }
248
+
249
+ var id = jsonObject.GetValueOrDefault<string>("id");
250
+
251
+ var sections = new List<IntermediateSection>();
252
+
253
+ var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections");
254
+ foreach (JsonObject sectionJson in sectionsJson)
255
+ {
256
+ var section = IntermediateSection.Deserialize(creator, sectionJson);
257
+ sections.Add(section);
258
+ }
259
+
260
+ var localizations = new Dictionary<string, Localization>(StringComparer.OrdinalIgnoreCase);
261
+
262
+ //var localizationsJson = jsonObject.GetValueOrDefault<JsonArray>("localizations") ?? new JsonArray();
263
+ //foreach (JsonObject localizationJson in localizationsJson)
264
+ //{
265
+ // var localization = Localization.Deserialize(localizationJson);
266
+ // localizations.Add(localization.Culture, localization);
267
+ //}
268
+
269
+ return new Intermediate(id, sections, localizations, null);
270
+ }
271
+
272
#if false
273
/// <summary>
274
/// Loads an intermediate from a path on disk.
@@ -344,5 +413,20 @@ namespace WixToolset.Data
413
writer.WriteEndElement();
414
}
415
#endif
416
+
417
+ private Dictionary<string, IntermediateTupleDefinition> GetCustomDefinitionsInSections()
418
+ {
419
+ var customDefinitions = new Dictionary<string, IntermediateTupleDefinition>();
420
+
421
+ foreach (var tuple in this.Sections.SelectMany(s => s.Tuples).Where(t => t.Definition.Type == TupleDefinitionType.MustBeFromAnExtension))
422
+ {
423
+ if (!customDefinitions.ContainsKey(tuple.Definition.Name))
424
+ {
425
+ customDefinitions.Add(tuple.Definition.Name, tuple.Definition);
426
+ }
427
+ }
428
+
429
+ return customDefinitions;
430
+ }
431
}
432
}
src/WixToolset.Data/IntermediateFieldExtensions.cs
+58
-14
@@ -11,6 +11,8 @@ namespace WixToolset.Data
11
12
public static IntermediateField Set(this IntermediateField field, object value)
13
{
14
+ var data = value;
15
+
16
if (field == null)
17
{
18
throw new ArgumentNullException(nameof(field));
@@ -21,30 +23,72 @@ namespace WixToolset.Data
23
}
24
else if (field.Type == IntermediateFieldType.Bool && !(value is bool))
25
{
24
- throw new ArgumentException(nameof(value));
26
+ if (value is int)
27
+ {
28
+ data = ((int)value) != 0;
29
+ }
30
+ else if (value is string str)
31
+ {
32
+ if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase))
33
+ {
34
+ data = true;
35
+ }
36
+ else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase))
37
+ {
38
+ data = false;
39
+ }
40
+ else
41
+ {
42
+ throw new ArgumentException(nameof(value));
43
+ }
44
+ }
45
+ else
46
+ {
47
+ throw new ArgumentException(nameof(value));
48
+ }
49
}
50
else if (field.Type == IntermediateFieldType.Number && !(value is int))
51
{
28
- throw new ArgumentException(nameof(value));
52
+ if (value is string str && Int32.TryParse(str, out var number))
53
+ {
54
+ data = number;
55
+ }
56
+ else
57
+ {
58
+ throw new ArgumentException(nameof(value));
59
+ }
60
}
61
else if (field.Type == IntermediateFieldType.String && !(value is string))
62
{
32
- throw new ArgumentException(nameof(value));
33
- }
34
- else if (field.Type == IntermediateFieldType.Path && !(value is IntermediateFieldPathValue || value is string))
35
- {
36
- throw new ArgumentException(nameof(value));
37
- }
38
-
39
- if (field.Type == IntermediateFieldType.Path && value != null && value is string)
40
- {
41
- value = new IntermediateFieldPathValue { Path = (string)value };
63
+ if (value is int)
64
+ {
65
+ data = value.ToString();
66
+ }
67
+ else if (value is bool b)
68
+ {
69
+ data = b ? "true" : "false";
70
+ }
71
+ else
72
+ {
73
+ throw new ArgumentException(nameof(value));
74
+ }
75
+ }
76
+ else if (field.Type == IntermediateFieldType.Path && !(value is IntermediateFieldPathValue))
77
+ {
78
+ if (value is string str)
79
+ {
80
+ data = new IntermediateFieldPathValue { Path = str };
81
+ }
82
+ else
83
+ {
84
+ throw new ArgumentException(nameof(value));
85
+ }
86
}
87
88
field.Value = new IntermediateFieldValue
89
{
90
Context = valueContext,
47
- Data = value,
91
+ Data = data,
92
PreviousValue = field.Value
93
};
94
@@ -103,7 +147,7 @@ namespace WixToolset.Data
147
return field.Value.AsNumber() != 0;
148
149
case IntermediateFieldType.String:
106
- return !System.String.IsNullOrEmpty(field.Value.AsString());
150
+ return !String.IsNullOrEmpty(field.Value.AsString());
151
152
default:
153
throw new InvalidCastException($"Cannot convert field {field.Name} with type {field.Type} to boolean");
src/WixToolset.Data/IntermediateFieldValueExtensions.cs
+71
-5
@@ -2,26 +2,71 @@
2
3
namespace WixToolset.Data
4
{
5
+ using System;
6
+
7
public static class IntermediateFieldValueExtensions
8
{
9
public static bool AsBool(this IntermediateFieldValue value)
10
{
9
- return value?.Data == null ? false : (bool)value.Data;
11
+ var result = value.AsNullableBool();
12
+ return result.HasValue && result.Value;
13
}
14
15
public static bool? AsNullableBool(this IntermediateFieldValue value)
16
{
14
- return (bool?)value?.Data;
17
+ if (value?.Data == null)
18
+ {
19
+ return null;
20
+ }
21
+ else if (value.Data is bool b)
22
+ {
23
+ return b;
24
+ }
25
+ else if (value.Data is int n)
26
+ {
27
+ return n != 0;
28
+ }
29
+ else if (value.Data is string s)
30
+ {
31
+ if (s.Equals("yes", StringComparison.OrdinalIgnoreCase) || s.Equals("true", StringComparison.OrdinalIgnoreCase))
32
+ {
33
+ return true;
34
+ }
35
+ else if (s.Equals("no", StringComparison.OrdinalIgnoreCase) || s.Equals("false", StringComparison.OrdinalIgnoreCase))
36
+ {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ return (bool)value.Data;
42
}
43
44
public static int AsNumber(this IntermediateFieldValue value)
45
{
19
- return value?.Data == null ? 0 : (int)value.Data;
46
+ var result = value.AsNullableNumber();
47
+ return result ?? 0;
48
}
49
50
public static int? AsNullableNumber(this IntermediateFieldValue value)
51
{
24
- return (int?)value?.Data;
52
+ if (value?.Data == null)
53
+ {
54
+ return null;
55
+ }
56
+ else if (value.Data is int n)
57
+ {
58
+ return n;
59
+ }
60
+ else if (value.Data is bool b)
61
+ {
62
+ return b ? 1 : 0;
63
+ }
64
+ else if (value.Data is string s)
65
+ {
66
+ return Convert.ToInt32(s);
67
+ }
68
+
69
+ return (int)value.Data;
70
}
71
72
public static IntermediateFieldPathValue AsPath(this IntermediateFieldValue value)
@@ -31,7 +76,28 @@ namespace WixToolset.Data
76
77
public static string AsString(this IntermediateFieldValue value)
78
{
34
- return (string)value?.Data;
79
+ if (value?.Data == null)
80
+ {
81
+ return null;
82
+ }
83
+ else if (value.Data is string s)
84
+ {
85
+ return s;
86
+ }
87
+ else if (value.Data is int n)
88
+ {
89
+ return n.ToString();
90
+ }
91
+ else if (value.Data is bool b)
92
+ {
93
+ return b ? "true" : "false";
94
+ }
95
+ else if (value.Data is IntermediateFieldPathValue p)
96
+ {
97
+ return p.Path;
98
+ }
99
+
100
+ return (string)value.Data;
101
}
102
}
103
}
src/WixToolset.Data/IntermediateSection.cs
+2
-1
@@ -66,7 +66,6 @@ namespace WixToolset.Data
66
var codepage = jsonObject.GetValueOrDefault("codepage", 0);
67
var id = jsonObject.GetValueOrDefault<string>("id");
68
var type = jsonObject.GetEnumOrDefault("type", SectionType.Unknown);
69
- var tuplesJson = jsonObject.GetValueOrDefault<JsonArray>("tuples");
69
70
if (null == id && (SectionType.Unknown != type && SectionType.Fragment != type))
71
{
@@ -80,6 +79,8 @@ namespace WixToolset.Data
79
80
var section = new IntermediateSection(id, type, codepage);
81
82
+ var tuplesJson = jsonObject.GetValueOrDefault<JsonArray>("tuples");
83
+
84
foreach (JsonObject tupleJson in tuplesJson)
85
{
86
var tuple = IntermediateTuple.Deserialize(creator, tupleJson);
src/WixToolset.Data/IntermediateTuple.cs
+7
-7
@@ -6,9 +6,9 @@ namespace WixToolset.Data
6
7
public class IntermediateTuple
8
{
9
- //public IntermediateTuple(IntermediateTupleDefinition definition) : this(definition, null, null)
10
- //{
11
- //}
9
+ public IntermediateTuple(IntermediateTupleDefinition definition) : this(definition, null, null)
10
+ {
11
+ }
12
13
public IntermediateTuple(IntermediateTupleDefinition definition, SourceLineNumber sourceLineNumber, Identifier id = null)
14
{
@@ -35,11 +35,11 @@ namespace WixToolset.Data
35
var sourceLineNumbersJson = jsonObject.GetValueOrDefault<JsonObject>("ln");
36
var fieldsJson = jsonObject.GetValueOrDefault<JsonArray>("fields");
37
38
- creator.TryGetTupleDefinitionByName(definitionName, out var definition); // TODO: this isn't sufficient.
39
- var tuple = definition.CreateTuple();
38
+ var id = (idJson == null) ? null : Identifier.Deserialize(idJson);
39
+ var sourceLineNumbers = (sourceLineNumbersJson == null) ? null : SourceLineNumber.Deserialize(sourceLineNumbersJson);
40
41
- tuple.Id = (idJson == null) ? null : Identifier.Deserialize(idJson);
42
- tuple.SourceLineNumbers = (sourceLineNumbersJson == null) ? null : SourceLineNumber.Deserialize(sourceLineNumbersJson);
41
+ creator.TryGetTupleDefinitionByName(definitionName, out var definition); // TODO: this isn't sufficient.
42
+ var tuple = definition.CreateTuple(sourceLineNumbers, id);
43
44
for (var i = 0; i < fieldsJson.Count; ++i)
45
{
src/WixToolset.Data/IntermediateTupleDefinition.cs
+49
-1
@@ -3,6 +3,7 @@
3
namespace WixToolset.Data
4
{
5
using System;
6
+ using SimpleJson;
7
8
public class IntermediateTupleDefinition
9
{
@@ -23,7 +24,7 @@ namespace WixToolset.Data
24
this.FieldDefinitions = fieldDefinitions;
25
this.StrongTupleType = strongTupleType ?? typeof(IntermediateTuple);
26
#if DEBUG
26
- if (!this.StrongTupleType.IsSubclassOf(typeof(IntermediateTuple))) throw new ArgumentException(nameof(strongTupleType));
27
+ if (this.StrongTupleType != typeof(IntermediateTuple) && !this.StrongTupleType.IsSubclassOf(typeof(IntermediateTuple))) throw new ArgumentException(nameof(strongTupleType));
28
#endif
29
}
30
@@ -43,5 +44,52 @@ namespace WixToolset.Data
44
45
return result;
46
}
47
+
48
+ internal static IntermediateTupleDefinition Deserialize(JsonObject jsonObject)
49
+ {
50
+ var name = jsonObject.GetValueOrDefault<string>("name");
51
+ var definitionsJson = jsonObject.GetValueOrDefault<JsonArray>("fields");
52
+
53
+ var fieldDefinitions = new IntermediateFieldDefinition[definitionsJson.Count];
54
+
55
+ for (var i = 0; i < definitionsJson.Count; ++i)
56
+ {
57
+ var definitionJson = (JsonObject)definitionsJson[i];
58
+ var fieldName = definitionJson.GetValueOrDefault<string>("name");
59
+ var fieldType = definitionJson.GetEnumOrDefault("type", IntermediateFieldType.String);
60
+ fieldDefinitions[i] = new IntermediateFieldDefinition(fieldName, fieldType);
61
+ }
62
+
63
+ return new IntermediateTupleDefinition(name, fieldDefinitions, null);
64
+ }
65
+
66
+ internal JsonObject Serialize()
67
+ {
68
+ var jsonObject = new JsonObject
69
+ {
70
+ { "name", this.Name }
71
+ };
72
+
73
+ var fieldsJson = new JsonArray(this.FieldDefinitions.Length);
74
+
75
+ foreach (var fieldDefinition in this.FieldDefinitions)
76
+ {
77
+ var fieldJson = new JsonObject
78
+ {
79
+ { "name", fieldDefinition.Name },
80
+ };
81
+
82
+ if (fieldDefinition.Type != IntermediateFieldType.String)
83
+ {
84
+ fieldJson.Add("type", fieldDefinition.Type.ToString().ToLowerInvariant());
85
+ }
86
+
87
+ fieldsJson.Add(fieldJson);
88
+ }
89
+
90
+ jsonObject.Add("fields", fieldsJson);
91
+
92
+ return jsonObject;
93
+ }
94
}
95
}
src/WixToolset.Data/IntermediateTupleExtensions.cs
+1
-1
@@ -8,7 +8,7 @@ namespace WixToolset.Data
8
{
9
var definition = tuple.Definition.FieldDefinitions[index];
10
11
- var field = tuple.Fields[index].Set(definition, value); ;
11
+ var field = tuple.Fields[index].Set(definition, value);
12
13
return tuple.Fields[index] = field;
14
}
src/WixToolset.Data/SimpleTupleDefinitionCreator.cs
+16
-1
@@ -2,12 +2,27 @@
2
3
namespace WixToolset.Data
4
{
5
+ using System.Collections.Generic;
6
+
7
internal class SimpleTupleDefinitionCreator : ITupleDefinitionCreator
8
{
9
+ private Dictionary<string, IntermediateTupleDefinition> CustomDefinitionByName { get; } = new Dictionary<string, IntermediateTupleDefinition>();
10
+
11
+ public void AddCustomTupleDefinition(IntermediateTupleDefinition definition)
12
+ {
13
+ this.CustomDefinitionByName.Add(definition.Name, definition);
14
+ }
15
+
16
public bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition)
17
{
18
tupleDefinition = TupleDefinitions.ByName(name);
19
+
20
+ if (tupleDefinition == null)
21
+ {
22
+ tupleDefinition = this.CustomDefinitionByName.GetValueOrDefault(name);
23
+ }
24
+
25
return tupleDefinition != null;
26
}
27
}
13
-}
\ No newline at end of file
28
+}
src/WixToolset.Data/Tuples/WixFileTuple.cs
+2
-2
@@ -131,9 +131,9 @@ namespace WixToolset.Data.Tuples
131
set => this.Set((int)WixFileTupleFields.DiskId, value);
132
}
133
134
- public string Source
134
+ public IntermediateFieldPathValue Source
135
{
136
- get => this.Fields[(int)WixFileTupleFields.Source].AsPath()?.Path;
136
+ get => this.Fields[(int)WixFileTupleFields.Source].AsPath();
137
set => this.Set((int)WixFileTupleFields.Source, value);
138
}
139