aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/api/wix/WixToolset.Extensibility/BaseOptimizerExtension.cs26
-rw-r--r--src/api/wix/WixToolset.Extensibility/Data/ICompileContext.cs2
-rw-r--r--src/api/wix/WixToolset.Extensibility/Data/IOptimizeContext.cs61
-rw-r--r--src/api/wix/WixToolset.Extensibility/IOptimizerExtension.cs22
-rw-r--r--src/wix/WixToolset.Core/CommandLine/BuildCommand.cs19
-rw-r--r--src/wix/WixToolset.Core/IOptimizer.cs17
-rw-r--r--src/wix/WixToolset.Core/OptimizeContext.cs39
-rw-r--r--src/wix/WixToolset.Core/Optimizer.cs36
-rw-r--r--src/wix/WixToolset.Core/WixToolsetServiceProvider.cs2
-rw-r--r--src/wix/test/Example.Extension/ExampleExtensionFactory.cs4
-rw-r--r--src/wix/test/Example.Extension/ExampleOptimizerExtension.cs22
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs4
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml2
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs4
14 files changed, 253 insertions, 7 deletions
diff --git a/src/api/wix/WixToolset.Extensibility/BaseOptimizerExtension.cs b/src/api/wix/WixToolset.Extensibility/BaseOptimizerExtension.cs
new file mode 100644
index 00000000..5bb89272
--- /dev/null
+++ b/src/api/wix/WixToolset.Extensibility/BaseOptimizerExtension.cs
@@ -0,0 +1,26 @@
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
3namespace WixToolset.Extensibility
4{
5 using WixToolset.Extensibility.Data;
6
7 /// <summary>
8 /// Base class for creating an optimizer extension.
9 /// </summary>
10 public abstract class BaseOptimizerExtension : IOptimizerExtension
11 {
12 /// <summary>
13 /// Called after all files have been compiled, before built-in optimizations, and before all sections are linked into a single section.
14 /// </summary>
15 public virtual void PreOptimize(IOptimizeContext context)
16 {
17 }
18
19 /// <summary>
20 /// Called after all files have been compiled, after built-in optimizations, and before all sections are linked into a single section.
21 /// </summary>
22 public virtual void PostOptimize(IOptimizeContext context)
23 {
24 }
25 }
26}
diff --git a/src/api/wix/WixToolset.Extensibility/Data/ICompileContext.cs b/src/api/wix/WixToolset.Extensibility/Data/ICompileContext.cs
index 7006fde8..cfccd0a9 100644
--- a/src/api/wix/WixToolset.Extensibility/Data/ICompileContext.cs
+++ b/src/api/wix/WixToolset.Extensibility/Data/ICompileContext.cs
@@ -55,7 +55,7 @@ namespace WixToolset.Extensibility.Data
55 XDocument Source { get; set; } 55 XDocument Source { get; set; }
56 56
57 /// <summary> 57 /// <summary>
58 /// Cancellation token to abort cancellation. 58 /// Cancellation token.
59 /// </summary> 59 /// </summary>
60 CancellationToken CancellationToken { get; set; } 60 CancellationToken CancellationToken { get; set; }
61 } 61 }
diff --git a/src/api/wix/WixToolset.Extensibility/Data/IOptimizeContext.cs b/src/api/wix/WixToolset.Extensibility/Data/IOptimizeContext.cs
new file mode 100644
index 00000000..5684ebcd
--- /dev/null
+++ b/src/api/wix/WixToolset.Extensibility/Data/IOptimizeContext.cs
@@ -0,0 +1,61 @@
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
3namespace WixToolset.Extensibility.Data
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Threading;
8 using WixToolset.Data;
9
10 /// <summary>
11 /// Context provided to the optimizer.
12 /// </summary>
13 public interface IOptimizeContext
14 {
15 /// <summary>
16 /// Service provider made available to the optimizer and its extensions.
17 /// </summary>
18 IServiceProvider ServiceProvider { get; }
19
20 /// <summary>
21 /// Set of extensions provided to the optimizer.
22 /// </summary>
23 IReadOnlyCollection<IOptimizerExtension> Extensions { get; set; }
24
25 /// <summary>
26 /// Intermediate folder.
27 /// </summary>
28 string IntermediateFolder { get; set; }
29
30 /// <summary>
31 /// Collection of bindpaths used to bind files.
32 /// </summary>
33 IReadOnlyCollection<IBindPath> BindPaths { get; set; }
34
35 /// <summary>
36 /// Bind variables used during optimization.
37 /// </summary>
38 IDictionary<string, string> BindVariables { get; set; }
39
40 /// <summary>
41 /// Gets or sets the platform which the optimizer will use when defaulting 64-bit symbol properties.
42 /// </summary>
43 /// <value>The platform which the optimizer will use when defaulting 64-bit symbol properties.</value>
44 Platform Platform { get; set; }
45
46 /// <summary>
47 /// Collection of intermediates to optimize.
48 /// </summary>
49 IReadOnlyCollection<Intermediate> Intermediates { get; set; }
50
51 /// <summary>
52 /// Collection of localization files to use in the optimizer.
53 /// </summary>
54 IReadOnlyCollection<Localization> Localizations { get; set; }
55
56 /// <summary>
57 /// Cancellation token.
58 /// </summary>
59 CancellationToken CancellationToken { get; set; }
60 }
61}
diff --git a/src/api/wix/WixToolset.Extensibility/IOptimizerExtension.cs b/src/api/wix/WixToolset.Extensibility/IOptimizerExtension.cs
new file mode 100644
index 00000000..589e7ecc
--- /dev/null
+++ b/src/api/wix/WixToolset.Extensibility/IOptimizerExtension.cs
@@ -0,0 +1,22 @@
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
3namespace WixToolset.Extensibility
4{
5 using WixToolset.Extensibility.Data;
6
7 /// <summary>
8 /// Interface that all optimizer extensions implement.
9 /// </summary>
10 public interface IOptimizerExtension
11 {
12 /// <summary>
13 /// Called after all files have been compiled, before built-in optimizations, and before all sections are linked into a single section.
14 /// </summary>
15 void PreOptimize(IOptimizeContext context);
16
17 /// <summary>
18 /// Called after all files have been compiled, after built-in optimizations, and before all sections are linked into a single section.
19 /// </summary>
20 void PostOptimize(IOptimizeContext context);
21 }
22}
diff --git a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
index 68dbd768..2ad18073 100644
--- a/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
+++ b/src/wix/WixToolset.Core/CommandLine/BuildCommand.cs
@@ -10,7 +10,6 @@ namespace WixToolset.Core.CommandLine
10 using System.Threading.Tasks; 10 using System.Threading.Tasks;
11 using System.Xml.Linq; 11 using System.Xml.Linq;
12 using WixToolset.Data; 12 using WixToolset.Data;
13 using WixToolset.Data.Bind;
14 using WixToolset.Extensibility; 13 using WixToolset.Extensibility;
15 using WixToolset.Extensibility.Data; 14 using WixToolset.Extensibility.Data;
16 using WixToolset.Extensibility.Services; 15 using WixToolset.Extensibility.Services;
@@ -112,6 +111,8 @@ namespace WixToolset.Core.CommandLine
112 return Task.FromResult(this.Messaging.LastErrorNumber); 111 return Task.FromResult(this.Messaging.LastErrorNumber);
113 } 112 }
114 113
114 this.OptimizePhase(wixobjs, wxls, this.commandLine.BindPaths, this.commandLine.BindVariables, cancellationToken);
115
115 if (inputsOutputs.OutputType == OutputType.Library) 116 if (inputsOutputs.OutputType == OutputType.Library)
116 { 117 {
117 using (new IntermediateFieldContext("wix.lib")) 118 using (new IntermediateFieldContext("wix.lib"))
@@ -207,6 +208,22 @@ namespace WixToolset.Core.CommandLine
207 return intermediates; 208 return intermediates;
208 } 209 }
209 210
211 private void OptimizePhase(IReadOnlyCollection<Intermediate> intermediates, IReadOnlyCollection<Localization> localizations, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, CancellationToken cancellationToken)
212 {
213 var context = this.ServiceProvider.GetService<IOptimizeContext>();
214 context.Extensions = this.ExtensionManager.GetServices<IOptimizerExtension>();
215 context.IntermediateFolder = this.IntermediateFolder;
216 context.BindPaths = bindPaths;
217 context.BindVariables = bindVariables;
218 context.Platform = this.Platform;
219 context.Intermediates = intermediates;
220 context.Localizations = localizations;
221 context.CancellationToken = cancellationToken;
222
223 var optimizer = this.ServiceProvider.GetService<IOptimizer>();
224 optimizer.Optimize(context);
225 }
226
210 private void LibraryPhase(IReadOnlyCollection<Intermediate> intermediates, IReadOnlyCollection<Localization> localizations, IEnumerable<string> libraryFiles, ISymbolDefinitionCreator creator, bool bindFiles, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, string outputPath, CancellationToken cancellationToken) 227 private void LibraryPhase(IReadOnlyCollection<Intermediate> intermediates, IReadOnlyCollection<Localization> localizations, IEnumerable<string> libraryFiles, ISymbolDefinitionCreator creator, bool bindFiles, IReadOnlyCollection<IBindPath> bindPaths, Dictionary<string, string> bindVariables, string outputPath, CancellationToken cancellationToken)
211 { 228 {
212 var libraries = this.LoadLibraries(libraryFiles, creator); 229 var libraries = this.LoadLibraries(libraryFiles, creator);
diff --git a/src/wix/WixToolset.Core/IOptimizer.cs b/src/wix/WixToolset.Core/IOptimizer.cs
new file mode 100644
index 00000000..85c90b80
--- /dev/null
+++ b/src/wix/WixToolset.Core/IOptimizer.cs
@@ -0,0 +1,17 @@
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
3namespace WixToolset.Core
4{
5 using WixToolset.Extensibility.Data;
6
7 /// <summary>
8 /// Interface for built-in optimizer.
9 /// </summary>
10 public interface IOptimizer
11 {
12 /// <summary>
13 /// Called after all files have been compiled and before all sections are linked into a single section.
14 /// </summary>
15 void Optimize(IOptimizeContext context);
16 }
17}
diff --git a/src/wix/WixToolset.Core/OptimizeContext.cs b/src/wix/WixToolset.Core/OptimizeContext.cs
new file mode 100644
index 00000000..93b6c354
--- /dev/null
+++ b/src/wix/WixToolset.Core/OptimizeContext.cs
@@ -0,0 +1,39 @@
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
3namespace WixToolset.Core
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Threading;
8 using WixToolset.Data;
9 using WixToolset.Extensibility;
10 using WixToolset.Extensibility.Data;
11
12 internal class OptimizeContext : IOptimizeContext
13 {
14 internal OptimizeContext(IServiceProvider serviceProvider)
15 {
16 this.ServiceProvider = serviceProvider;
17 }
18
19 public IServiceProvider ServiceProvider { get; }
20
21 public IReadOnlyCollection<IOptimizerExtension> Extensions { get; set; }
22
23 public string IntermediateFolder { get; set; }
24
25 public IReadOnlyCollection<IBindPath> BindPaths { get; set; }
26
27 public IDictionary<string, string> BindVariables { get; set; }
28
29 public Platform Platform { get; set; }
30
31 public bool IsCurrentPlatform64Bit => this.Platform == Platform.ARM64 || this.Platform == Platform.X64;
32
33 public IReadOnlyCollection<Intermediate> Intermediates { get; set; }
34
35 public IReadOnlyCollection<Localization> Localizations { get; set; }
36
37 public CancellationToken CancellationToken { get; set; }
38 }
39}
diff --git a/src/wix/WixToolset.Core/Optimizer.cs b/src/wix/WixToolset.Core/Optimizer.cs
new file mode 100644
index 00000000..5864121e
--- /dev/null
+++ b/src/wix/WixToolset.Core/Optimizer.cs
@@ -0,0 +1,36 @@
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
3namespace WixToolset.Core
4{
5 using System;
6 using WixToolset.Extensibility.Data;
7 using WixToolset.Extensibility.Services;
8
9 internal class Optimizer : IOptimizer
10 {
11 internal Optimizer(IServiceProvider serviceProvider)
12 {
13 this.ServiceProvider = serviceProvider;
14 this.Messaging = this.ServiceProvider.GetService<IMessaging>();
15 }
16
17 private IServiceProvider ServiceProvider { get; }
18
19 private IMessaging Messaging { get; }
20
21 public void Optimize(IOptimizeContext context)
22 {
23 foreach (var extension in context.Extensions)
24 {
25 extension.PreOptimize(context);
26 }
27
28 // TODO: Fill with useful optimization features.
29
30 foreach (var extension in context.Extensions)
31 {
32 extension.PostOptimize(context);
33 }
34 }
35 }
36}
diff --git a/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs b/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
index 5620bcd2..cb8dbd87 100644
--- a/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
+++ b/src/wix/WixToolset.Core/WixToolsetServiceProvider.cs
@@ -37,6 +37,7 @@ namespace WixToolset.Core
37 this.AddService<ICommandLine>((provider, singletons) => new CommandLine.CommandLine(provider)); 37 this.AddService<ICommandLine>((provider, singletons) => new CommandLine.CommandLine(provider));
38 this.AddService<IPreprocessContext>((provider, singletons) => new PreprocessContext(provider)); 38 this.AddService<IPreprocessContext>((provider, singletons) => new PreprocessContext(provider));
39 this.AddService<ICompileContext>((provider, singletons) => new CompileContext(provider)); 39 this.AddService<ICompileContext>((provider, singletons) => new CompileContext(provider));
40 this.AddService<IOptimizeContext>((provider, singletons) => new OptimizeContext(provider));
40 this.AddService<ILibraryContext>((provider, singletons) => new LibraryContext(provider)); 41 this.AddService<ILibraryContext>((provider, singletons) => new LibraryContext(provider));
41 this.AddService<ILibraryResult>((provider, singletons) => new LibraryResult()); 42 this.AddService<ILibraryResult>((provider, singletons) => new LibraryResult());
42 this.AddService<ILinkContext>((provider, singletons) => new LinkContext(provider)); 43 this.AddService<ILinkContext>((provider, singletons) => new LinkContext(provider));
@@ -58,6 +59,7 @@ namespace WixToolset.Core
58 59
59 this.AddService<IBinder>((provider, singletons) => new Binder(provider)); 60 this.AddService<IBinder>((provider, singletons) => new Binder(provider));
60 this.AddService<ICompiler>((provider, singletons) => new Compiler(provider)); 61 this.AddService<ICompiler>((provider, singletons) => new Compiler(provider));
62 this.AddService<IOptimizer>((provider, singletons) => new Optimizer(provider));
61 this.AddService<ILayoutCreator>((provider, singletons) => new LayoutCreator(provider)); 63 this.AddService<ILayoutCreator>((provider, singletons) => new LayoutCreator(provider));
62 this.AddService<IPreprocessor>((provider, singletons) => new Preprocessor(provider)); 64 this.AddService<IPreprocessor>((provider, singletons) => new Preprocessor(provider));
63 this.AddService<ILibrarian>((provider, singletons) => new Librarian(provider)); 65 this.AddService<ILibrarian>((provider, singletons) => new Librarian(provider));
diff --git a/src/wix/test/Example.Extension/ExampleExtensionFactory.cs b/src/wix/test/Example.Extension/ExampleExtensionFactory.cs
index 0b0fb836..16eea6dc 100644
--- a/src/wix/test/Example.Extension/ExampleExtensionFactory.cs
+++ b/src/wix/test/Example.Extension/ExampleExtensionFactory.cs
@@ -35,6 +35,10 @@ namespace Example.Extension
35 { 35 {
36 extension = new ExampleCompilerExtension(); 36 extension = new ExampleCompilerExtension();
37 } 37 }
38 else if (extensionType == typeof(IOptimizerExtension))
39 {
40 extension = new ExampleOptimizerExtension();
41 }
38 else if (extensionType == typeof(IExtensionData)) 42 else if (extensionType == typeof(IExtensionData))
39 { 43 {
40 extension = new ExampleExtensionData(); 44 extension = new ExampleExtensionData();
diff --git a/src/wix/test/Example.Extension/ExampleOptimizerExtension.cs b/src/wix/test/Example.Extension/ExampleOptimizerExtension.cs
new file mode 100644
index 00000000..6a2cb91e
--- /dev/null
+++ b/src/wix/test/Example.Extension/ExampleOptimizerExtension.cs
@@ -0,0 +1,22 @@
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
3namespace Example.Extension
4{
5 using System.Linq;
6 using WixToolset.Extensibility;
7 using WixToolset.Extensibility.Data;
8
9 internal class ExampleOptimizerExtension : BaseOptimizerExtension
10 {
11 public override void PostOptimize(IOptimizeContext context)
12 {
13 foreach (var intermediate in context.Intermediates)
14 {
15 foreach (var symbol in intermediate.Sections.SelectMany(s=>s.Symbols).OfType<ExampleSymbol>())
16 {
17 symbol.Value = $"{symbol.Value} <optimized>";
18 }
19 }
20 }
21 }
22}
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
index 710f3b8d..429226f5 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/ExtensionFixture.cs
@@ -24,7 +24,7 @@ namespace WixToolsetTest.CoreIntegration
24 var results = build.BuildAndQuery(Build, "Wix4Example"); 24 var results = build.BuildAndQuery(Build, "Wix4Example");
25 WixAssert.CompareLineByLine(new[] 25 WixAssert.CompareLineByLine(new[]
26 { 26 {
27 "Wix4Example:Foo\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tBar" 27 "Wix4Example:Foo\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tBar <optimized>"
28 }, results); 28 }, results);
29 } 29 }
30 30
@@ -92,7 +92,7 @@ namespace WixToolsetTest.CoreIntegration
92 var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single(); 92 var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single();
93 WixAssert.StringEqual("Foo", example.Id?.Id); 93 WixAssert.StringEqual("Foo", example.Id?.Id);
94 WixAssert.StringEqual("filF5_pLhBuF5b4N9XEo52g_hUM5Lo", example[0].AsString()); 94 WixAssert.StringEqual("filF5_pLhBuF5b4N9XEo52g_hUM5Lo", example[0].AsString());
95 WixAssert.StringEqual("Bar", example[1].AsString()); 95 WixAssert.StringEqual("Bar <optimized>", example[1].AsString());
96 } 96 }
97 } 97 }
98 98
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml
index 42ececb1..0375b3b6 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/ExampleExtension/Decompiled-Expected.xml
@@ -5,7 +5,7 @@
5 <StandardDirectory Id="ProgramFilesFolder"> 5 <StandardDirectory Id="ProgramFilesFolder">
6 <Directory Id="INSTALLFOLDER" ShortName="oekcr5lq" Name="MsiPackage"> 6 <Directory Id="INSTALLFOLDER" ShortName="oekcr5lq" Name="MsiPackage">
7 <Component Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Guid="{GUID}" Bitness="always32"> 7 <Component Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Guid="{GUID}" Bitness="always32">
8 <Example Id="Foo" Value="Bar" xmlns="http://www.example.com/scheams/v1/wxs" /> 8 <Example Id="Foo" Value="Bar &lt;optimized&gt;" xmlns="http://www.example.com/scheams/v1/wxs" />
9 <File Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Name="example.txt" KeyPath="yes" Source="PFiles\MsiPackage\example.txt" /> 9 <File Id="filF5_pLhBuF5b4N9XEo52g_hUM5Lo" Name="example.txt" KeyPath="yes" Source="PFiles\MsiPackage\example.txt" />
10 </Component> 10 </Component>
11 </Directory> 11 </Directory>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs
index 76326741..0cd8a542 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/WixlibFixture.cs
@@ -288,7 +288,7 @@ namespace WixToolsetTest.CoreIntegration
288 288
289 var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single(); 289 var example = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).Single();
290 WixAssert.StringEqual("Foo", example.Id?.Id); 290 WixAssert.StringEqual("Foo", example.Id?.Id);
291 WixAssert.StringEqual("Bar", example[1].AsString()); 291 WixAssert.StringEqual("Bar <optimized>", example[1].AsString());
292 } 292 }
293 } 293 }
294 294
@@ -351,7 +351,7 @@ namespace WixToolsetTest.CoreIntegration
351 var examples = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).ToArray(); 351 var examples = section.Symbols.Where(t => t.Definition.Type == SymbolDefinitionType.MustBeFromAnExtension).ToArray();
352 WixAssert.CompareLineByLine(new[] { "Foo", "Other" }, examples.Select(t => t.Id?.Id).ToArray()); 352 WixAssert.CompareLineByLine(new[] { "Foo", "Other" }, examples.Select(t => t.Id?.Id).ToArray());
353 WixAssert.CompareLineByLine(new[] { "filF5_pLhBuF5b4N9XEo52g_hUM5Lo", "filvxdStJhRE_M5kbpLsTZJXbs34Sg" }, examples.Select(t => t[0].AsString()).ToArray()); 353 WixAssert.CompareLineByLine(new[] { "filF5_pLhBuF5b4N9XEo52g_hUM5Lo", "filvxdStJhRE_M5kbpLsTZJXbs34Sg" }, examples.Select(t => t[0].AsString()).ToArray());
354 WixAssert.CompareLineByLine(new[] { "Bar", "Value" }, examples.Select(t => t[1].AsString()).ToArray()); 354 WixAssert.CompareLineByLine(new[] { "Bar <optimized>", "Value <optimized>" }, examples.Select(t => t[1].AsString()).ToArray());
355 } 355 }
356 } 356 }
357 } 357 }