@joebigelow / wix / commits / 1d6ff8af

Standardize creation of public objects in move towards interfaces

Rob Mensching committed Dec 26, 2017 at 15:11 UTC 1d6ff8af3c423ee4622185edc986ae5caad6b122
13 files changed +293 -240
src/WixToolset.BuildTasks/DoIt.cs
-1
@@ -157,7 +157,6 @@ namespace WixToolset.BuildTasks
157 commandLineBuilder.AppendSwitchIfNotNull("-contentsfile ", this.BindContentsFile);
158 commandLineBuilder.AppendSwitchIfNotNull("-outputsfile ", this.BindOutputsFile);
159 commandLineBuilder.AppendSwitchIfNotNull("-builtoutputsfile ", this.BindBuiltOutputsFile);
160 - commandLineBuilder.AppendSwitchIfNotNull("-wixprojectfile ", this.WixProjectFile);
160
161 commandLineBuilder.AppendIfTrue("-bindFiles", this.BindFiles);
162 commandLineBuilder.AppendArrayIfNotNull("-bindPath ", this.CalculateBindPathStrings());
src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs
-3
@@ -9,9 +9,6 @@ namespace WixToolset.Core.Burn.Bundles
9 using System.Security.Cryptography;
10 using System.Security.Cryptography.X509Certificates;
11 using System.Text;
12 - using WixToolset.Data;
13 - using WixToolset.Data.Bind;
14 - using WixToolset.Data.Rows;
12
13 internal class ProcessPayloadsCommand
14 {
src/WixToolset.Core/Binder.cs
+7 -7
@@ -125,19 +125,19 @@ namespace WixToolset.Core
125 {
126 var entrySection = output.Sections.First(s => s.Type != SectionType.Fragment);
127
128 - Assembly executingAssembly = Assembly.GetExecutingAssembly();
129 - FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executingAssembly.Location);
128 + var executingAssembly = Assembly.GetExecutingAssembly();
129 + var fileVersion = FileVersionInfo.GetVersionInfo(executingAssembly.Location);
130
131 - var buildInfoRow = new WixBuildInfoTuple();
132 - buildInfoRow.WixVersion = fileVersion.FileVersion;
133 - buildInfoRow.WixOutputFile = outputFile;
131 + var buildInfoTuple = new WixBuildInfoTuple();
132 + buildInfoTuple.WixVersion = fileVersion.FileVersion;
133 + buildInfoTuple.WixOutputFile = outputFile;
134
135 if (!String.IsNullOrEmpty(outputPdbPath))
136 {
137 - buildInfoRow.WixPdbFile = outputPdbPath;
137 + buildInfoTuple.WixPdbFile = outputPdbPath;
138 }
139
140 - entrySection.Tuples.Add(buildInfoRow);
140 + entrySection.Tuples.Add(buildInfoTuple);
141 }
142 }
143 }
src/WixToolset.Core/CommandLine/BuildCommand.cs
+40 -49
@@ -13,11 +13,11 @@ namespace WixToolset.Core.CommandLine
13
14 internal class BuildCommand : ICommandLineCommand
15 {
16 - public BuildCommand(IServiceProvider serviceProvider, IMessaging messaging, IExtensionManager extensions, IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables, IEnumerable<string> locFiles, IEnumerable<string> libraryFiles, string outputPath, OutputType outputType, string cabCachePath, IEnumerable<string> cultures, bool bindFiles, IEnumerable<BindPath> bindPaths, string intermediateFolder, string contentsFile, string outputsFile, string builtOutputsFile)
16 + public BuildCommand(IServiceProvider serviceProvider, IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables, IEnumerable<string> locFiles, IEnumerable<string> libraryFiles, string outputPath, OutputType outputType, string cabCachePath, IEnumerable<string> cultures, bool bindFiles, IEnumerable<BindPath> bindPaths, string intermediateFolder, string contentsFile, string outputsFile, string builtOutputsFile)
17 {
18 this.ServiceProvider = serviceProvider;
19 - this.Messaging = messaging;
20 - this.ExtensionManager = extensions;
19 + this.Messaging = serviceProvider.GetService<IMessaging>();
20 + this.ExtensionManager = serviceProvider.GetService<IExtensionManager>();
21 this.LocFiles = locFiles;
22 this.LibraryFiles = libraryFiles;
23 this.PreprocessorVariables = preprocessorVariables;
@@ -76,6 +76,11 @@ namespace WixToolset.Core.CommandLine
76 {
77 var intermediates = this.CompilePhase();
78
79 + if (this.Messaging.EncounteredError)
80 + {
81 + return this.Messaging.LastErrorNumber;
82 + }
83 +
84 if (!intermediates.Any())
85 {
86 return 1;
@@ -112,35 +117,30 @@ namespace WixToolset.Core.CommandLine
117
118 foreach (var sourceFile in this.SourceFiles)
119 {
115 - var preprocessContext = this.ServiceProvider.GetService<IPreprocessContext>();
116 - preprocessContext.Messaging = this.Messaging;
117 - preprocessContext.Extensions = this.ExtensionManager.Create<IPreprocessorExtension>();
118 - preprocessContext.Platform = Platform.X86; // TODO: set this correctly
119 - preprocessContext.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List<string>();
120 - preprocessContext.SourceFile = sourceFile.SourcePath;
121 - preprocessContext.Variables = new Dictionary<string, string>(this.PreprocessorVariables);
120 + var preprocessor = new Preprocessor(this.ServiceProvider);
121 + preprocessor.IncludeSearchPaths = this.IncludeSearchPaths;
122 + preprocessor.Platform = Platform.X86; // TODO: set this correctly
123 + preprocessor.SourcePath = sourceFile.SourcePath;
124 + preprocessor.Variables = this.PreprocessorVariables;
125 + var document = preprocessor.Execute();
126 +
127 + if (this.Messaging.EncounteredError)
128 + {
129 + continue;
130 + }
131
123 - var preprocessor = new Preprocessor();
124 - var document = preprocessor.Process(preprocessContext);
132 + var compiler = new Compiler(this.ServiceProvider);
133 + compiler.OutputPath = sourceFile.OutputPath;
134 + compiler.Platform = Platform.X86; // TODO: set this correctly
135 + compiler.SourceDocument = document;
136 + var intermediate = compiler.Execute();
137
126 - if (!this.Messaging.EncounteredError)
138 + if (this.Messaging.EncounteredError)
139 {
128 - var compileContext = this.ServiceProvider.GetService<ICompileContext>();
129 - compileContext.Messaging = this.Messaging;
130 - compileContext.CompilationId = Guid.NewGuid().ToString("N");
131 - compileContext.Extensions = this.ExtensionManager.Create<ICompilerExtension>();
132 - compileContext.OutputPath = sourceFile.OutputPath;
133 - compileContext.Platform = Platform.X86; // TODO: set this correctly
134 - compileContext.Source = document;
135 -
136 - var compiler = new Compiler();
137 - var intermediate = compiler.Compile(compileContext);
138 -
139 - if (!this.Messaging.EncounteredError)
140 - {
141 - intermediates.Add(intermediate);
142 - }
140 + continue;
141 }
142 +
143 + intermediates.Add(intermediate);
144 }
145
146 return intermediates;
@@ -156,17 +156,12 @@ namespace WixToolset.Core.CommandLine
156 return null;
157 }
158
159 - var context = new LibraryContext();
160 - context.Messaging = this.Messaging;
161 - context.BindFiles = this.BindFiles;
162 - context.BindPaths = this.BindPaths;
163 - context.Extensions = this.ExtensionManager.Create<ILibrarianExtension>();
164 - context.Localizations = localizations;
165 - context.LibraryId = Guid.NewGuid().ToString("N");
166 - context.Intermediates = intermediates;
167 -
168 - var librarian = new Librarian();
169 - return librarian.Combine(context);
159 + var librarian = new Librarian(this.ServiceProvider);
160 + librarian.BindFiles = this.BindFiles;
161 + librarian.BindPaths = this.BindPaths;
162 + librarian.Intermediates = intermediates;
163 + librarian.Localizations = localizations;
164 + return librarian.Execute();
165 }
166
167 private Intermediate LinkPhase(IEnumerable<Intermediate> intermediates)
@@ -180,16 +175,12 @@ namespace WixToolset.Core.CommandLine
175 return null;
176 }
177
183 - var context = this.ServiceProvider.GetService<ILinkContext>();
184 - context.Messaging = this.Messaging;
185 - context.Extensions = this.ExtensionManager.Create<ILinkerExtension>();
186 - context.ExtensionData = this.ExtensionManager.Create<IExtensionData>();
187 - context.ExpectedOutputType = this.OutputType;
188 - context.Intermediates = intermediates.Union(libraries).ToList();
189 - context.TupleDefinitionCreator = creator;
190 -
191 - var linker = new Linker();
192 - return linker.Link(context);
178 + var linker = new Linker(this.ServiceProvider);
179 + linker.OutputType = this.OutputType;
180 + linker.Intermediates = intermediates;
181 + linker.Libraries = libraries;
182 + linker.TupleDefinitionCreator = creator;
183 + return linker.Execute();
184 }
185
186 private void BindPhase(Intermediate output)
src/WixToolset.Core/CommandLine/CommandLineParser.cs
+2 -2
@@ -207,14 +207,14 @@ namespace WixToolset.Core.CommandLine
207 var variables = this.GatherPreprocessorVariables(defines);
208 var bindPathList = this.GatherBindPaths(bindPaths);
209 var type = CalculateOutputType(outputType, outputFile);
210 - return new BuildCommand(this.ServiceProvider, this.Messaging, this.ExtensionManager, sourceFiles, variables, locFiles, libraryFiles, outputFile, type, cabCachePath, cultures, bindFiles, bindPathList, intermediateFolder, contentsFile, outputsFile, builtOutputsFile);
210 + return new BuildCommand(this.ServiceProvider, sourceFiles, variables, locFiles, libraryFiles, outputFile, type, cabCachePath, cultures, bindFiles, bindPathList, intermediateFolder, contentsFile, outputsFile, builtOutputsFile);
211 }
212
213 case Commands.Compile:
214 {
215 var sourceFiles = GatherSourceFiles(files, outputFolder);
216 var variables = GatherPreprocessorVariables(defines);
217 - return new CompileCommand(this.ServiceProvider, this.Messaging, this.ExtensionManager, sourceFiles, variables);
217 + return new CompileCommand(this.ServiceProvider, sourceFiles, variables);
218 }
219 }
220
src/WixToolset.Core/CommandLine/CompileCommand.cs
+13 -29
@@ -4,28 +4,21 @@ namespace WixToolset.Core.CommandLine
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Linq;
7 using WixToolset.Data;
8 using WixToolset.Extensibility;
9 using WixToolset.Extensibility.Services;
10
11 internal class CompileCommand : ICommandLineCommand
12 {
14 - public CompileCommand(IServiceProvider serviceProvider, IMessaging messaging, IExtensionManager extensions, IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables)
13 + public CompileCommand(IServiceProvider serviceProvider, IEnumerable<SourceFile> sources, IDictionary<string, string> preprocessorVariables)
14 {
15 this.PreprocessorVariables = preprocessorVariables;
16 this.ServiceProvider = serviceProvider;
18 - this.Messaging = messaging;
19 - this.ExtensionManager = extensions;
17 this.SourceFiles = sources;
18 }
19
20 private IServiceProvider ServiceProvider { get; }
21
25 - private IMessaging Messaging { get; }
26 -
27 - private IExtensionManager ExtensionManager { get; }
28 -
22 public IEnumerable<string> IncludeSearchPaths { get; }
23
24 private IEnumerable<SourceFile> SourceFiles { get; }
@@ -36,27 +29,18 @@ namespace WixToolset.Core.CommandLine
29 {
30 foreach (var sourceFile in this.SourceFiles)
31 {
39 - var preprocessContext = this.ServiceProvider.GetService<IPreprocessContext>();
40 - preprocessContext.Messaging = this.Messaging;
41 - preprocessContext.Extensions = this.ExtensionManager.Create<IPreprocessorExtension>();
42 - preprocessContext.Platform = Platform.X86; // TODO: set this correctly
43 - preprocessContext.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List<string>();
44 - preprocessContext.SourceFile = sourceFile.SourcePath;
45 - preprocessContext.Variables = new Dictionary<string, string>(this.PreprocessorVariables);
46 -
47 - var preprocessor = new Preprocessor();
48 - var document = preprocessor.Process(preprocessContext);
49 -
50 - var compileContext = this.ServiceProvider.GetService<ICompileContext>();
51 - compileContext.Messaging = this.Messaging;
52 - compileContext.CompilationId = Guid.NewGuid().ToString("N");
53 - compileContext.Extensions = this.ExtensionManager.Create<ICompilerExtension>();
54 - compileContext.OutputPath = sourceFile.OutputPath;
55 - compileContext.Platform = Platform.X86; // TODO: set this correctly
56 - compileContext.Source = document;
57 -
58 - var compiler = new Compiler();
59 - var intermediate = compiler.Compile(compileContext);
32 + var preprocessor = new Preprocessor(this.ServiceProvider);
33 + preprocessor.IncludeSearchPaths = this.IncludeSearchPaths;
34 + preprocessor.Platform = Platform.X86; // TODO: set this correctly
35 + preprocessor.SourcePath = sourceFile.SourcePath;
36 + preprocessor.Variables = new Dictionary<string, string>(this.PreprocessorVariables);
37 + var document = preprocessor.Execute();
38 +
39 + var compiler = new Compiler(this.ServiceProvider);
40 + compiler.OutputPath = sourceFile.OutputPath;
41 + compiler.Platform = Platform.X86; // TODO: set this correctly
42 + compiler.SourceDocument = document;
43 + var intermediate = compiler.Execute();
44
45 intermediate.Save(sourceFile.OutputPath);
46 }
src/WixToolset.Core/Compiler.cs
+28 -9
@@ -68,10 +68,25 @@ namespace WixToolset.Core
68 Icon,
69 }
70
71 + public Compiler(IServiceProvider serviceProvider)
72 + {
73 + this.ServiceProvider = serviceProvider;
74 + }
75 +
76 + private IServiceProvider ServiceProvider { get; }
77 +
78 private ICompileContext Context { get; set; }
79
80 private CompilerCore Core { get; set; }
81
82 + public string CompliationId { get; set; }
83 +
84 + public string OutputPath { get; set; }
85 +
86 + public Platform Platform { get; set; }
87 +
88 + public XDocument SourceDocument { get; set; }
89 +
90 /// <summary>
91 /// Gets or sets the platform which the compiler will use when defaulting 64-bit attributes and elements.
92 /// </summary>
@@ -87,17 +102,21 @@ namespace WixToolset.Core
102 /// <summary>
103 /// Compiles the provided Xml document into an intermediate object
104 /// </summary>
90 - /// <param name="context">Context for the compile. The BaseURI property
91 - /// should be properly set to get messages containing source line information.</param>
105 /// <returns>Intermediate object representing compiled source document.</returns>
106 /// <remarks>This method is not thread-safe.</remarks>
94 - public Intermediate Compile(ICompileContext context)
107 + public Intermediate Execute()
108 {
96 - this.Context = context ?? throw new ArgumentNullException(nameof(context));
109 + this.Context = this.ServiceProvider.GetService<ICompileContext>();
110 + this.Context.Messaging = this.ServiceProvider.GetService<IMessaging>();
111 + this.Context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<ICompilerExtension>();
112 + this.Context.CompilationId = this.CompliationId;
113 + this.Context.OutputPath = this.OutputPath;
114 + this.Context.Platform = this.Platform;
115 + this.Context.Source = this.SourceDocument;
116
117 var target = new Intermediate();
118
100 - if (String.IsNullOrEmpty(context.CompilationId))
119 + if (String.IsNullOrEmpty(this.Context.CompilationId))
120 {
121 this.Context.CompilationId = target.Id;
122 }
@@ -115,20 +134,20 @@ namespace WixToolset.Core
134 this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionXmlSchemaNamespace(extension.GetType().ToString(), extension.Namespace.NamespaceName, collidingExtension.GetType().ToString()));
135 }
136
118 - extension.PreCompile(context);
137 + extension.PreCompile(this.Context);
138 }
139
140 // Try to compile it.
141 try
142 {
124 - var parseHelper = context.ServiceProvider.GetService<IParseHelper>();
143 + var parseHelper = this.Context.ServiceProvider.GetService<IParseHelper>();
144
145 this.Core = new CompilerCore(target, this.Context.Messaging, parseHelper, extensionsByNamespace);
146 this.Core.ShowPedanticMessages = this.ShowPedanticMessages;
147 this.componentIdPlaceholdersResolver = new WixVariableResolver(this.Context.Messaging);
148
149 // parse the document
131 - var source = context.Source;
150 + var source = this.Context.Source;
151 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.Root);
152 if ("Wix" == source.Root.Name.LocalName)
153 {
@@ -158,7 +177,7 @@ namespace WixToolset.Core
177 }
178 finally
179 {
161 - foreach (var extension in context.Extensions)
180 + foreach (var extension in this.Context.Extensions)
181 {
182 extension.PostCompile(target);
183 }
src/WixToolset.Core/ExtensibilityServices/PreprocessHelper.cs
+5 -1
@@ -458,7 +458,11 @@ namespace WixToolset.Core.ExtensibilityServices
458 {
459 this.ExtensionsByPrefix = new Dictionary<string, IPreprocessorExtension>();
460
461 - foreach (var extension in context.Extensions)
461 + var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
462 +
463 + var extensions = extensionManager.Create<IPreprocessorExtension>();
464 +
465 + foreach (var extension in extensions)
466 {
467 if (null != extension.Prefixes)
468 {
src/WixToolset.Core/Librarian.cs
+25 -7
@@ -9,27 +9,45 @@ namespace WixToolset.Core
9 using WixToolset.Core.Link;
10 using WixToolset.Data;
11 using WixToolset.Extensibility;
12 + using WixToolset.Extensibility.Services;
13
14 /// <summary>
15 /// Core librarian tool.
16 /// </summary>
17 public sealed class Librarian
18 {
19 + public Librarian(IServiceProvider serviceProvider)
20 + {
21 + this.ServiceProvider = serviceProvider;
22 + }
23 +
24 + private IServiceProvider ServiceProvider { get; }
25 +
26 private ILibraryContext Context { get; set; }
27
28 + public bool BindFiles { get; set; }
29 +
30 + public IEnumerable<BindPath> BindPaths { get; set; }
31 +
32 + public IEnumerable<Localization> Localizations { get; set; }
33 +
34 + public IEnumerable<Intermediate> Intermediates { get; set; }
35 +
36 /// <summary>
37 /// Create a library by combining several intermediates (objects).
38 /// </summary>
39 /// <param name="sections">The sections to combine into a library.</param>
40 /// <returns>Returns the new library.</returns>
25 - public Intermediate Combine(ILibraryContext context)
41 + public Intermediate Execute()
42 {
27 - this.Context = context ?? throw new ArgumentNullException(nameof(context));
28 -
29 - if (String.IsNullOrEmpty(this.Context.LibraryId))
30 - {
31 - this.Context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_');
32 - }
43 + this.Context = new LibraryContext(this.ServiceProvider);
44 + this.Context.Messaging = this.ServiceProvider.GetService<IMessaging>();
45 + this.Context.BindFiles = this.BindFiles;
46 + this.Context.BindPaths = this.BindPaths;
47 + this.Context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<ILibrarianExtension>();
48 + this.Context.Localizations = this.Localizations;
49 + this.Context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_');
50 + this.Context.Intermediates = this.Intermediates;
51
52 foreach (var extension in this.Context.Extensions)
53 {
src/WixToolset.Core/LibraryContext.cs
+5
@@ -10,6 +10,11 @@ namespace WixToolset.Core
10
11 public class LibraryContext : ILibraryContext
12 {
13 + public LibraryContext(IServiceProvider serviceProvider)
14 + {
15 + this.ServiceProvider = serviceProvider;
16 + }
17 +
18 public IServiceProvider ServiceProvider { get; }
19
20 public IMessaging Messaging { get; set; }
src/WixToolset.Core/Linker.cs
+26 -10
@@ -12,6 +12,7 @@ namespace WixToolset.Core
12 using WixToolset.Data;
13 using WixToolset.Data.Tuples;
14 using WixToolset.Extensibility;
15 + using WixToolset.Extensibility.Services;
16 using WixToolset.Link;
17
18 /// <summary>
@@ -27,14 +28,17 @@ namespace WixToolset.Core
28 /// <summary>
29 /// Creates a linker.
30 /// </summary>
30 - public Linker()
31 + public Linker(IServiceProvider serviceProvider)
32 {
33 + this.ServiceProvider = serviceProvider;
34 this.sectionIdOnRows = true; // TODO: what is the correct value for this?
35
36 //this.extensionData = new List<IExtensionData>();
37 //this.inspectorExtensions = new List<InspectorExtension>();
38 }
39
40 + private IServiceProvider ServiceProvider { get; }
41 +
42 private ILinkContext Context { get; set; }
43
44 /// <summary>
@@ -49,11 +53,13 @@ namespace WixToolset.Core
53 /// <value>The option to show pedantic messages.</value>
54 public bool ShowPedanticMessages { get; set; }
55
52 - /// <summary>
53 - /// Gets or sets the Wix variable resolver.
54 - /// </summary>
55 - /// <value>The Wix variable resolver.</value>
56 - //internal IBindVariableResolver WixVariableResolver { get; set; }
56 + public OutputType OutputType { get; set; }
57 +
58 + public IEnumerable<Intermediate> Intermediates { get; set; }
59 +
60 + public IEnumerable<Intermediate> Libraries { get; set; }
61 +
62 + public ITupleDefinitionCreator TupleDefinitionCreator { get; set; }
63
64 /// <summary>
65 /// Links a collection of sections into an output.
@@ -61,16 +67,26 @@ namespace WixToolset.Core
67 /// <param name="inputs">The collection of sections to link together.</param>
68 /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param>
69 /// <returns>Output object from the linking.</returns>
64 - public Intermediate Link(ILinkContext context)
70 + public Intermediate Execute()
71 {
66 - this.Context = context ?? throw new ArgumentNullException(nameof(context));
72 + var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
73 +
74 + var creator = this.TupleDefinitionCreator ?? this.ServiceProvider.GetService<ITupleDefinitionCreator>();
75 +
76 + this.Context = this.ServiceProvider.GetService<ILinkContext>();
77 + this.Context.Messaging = this.ServiceProvider.GetService<IMessaging>();
78 + this.Context.Extensions = extensionManager.Create<ILinkerExtension>();
79 + this.Context.ExtensionData = extensionManager.Create<IExtensionData>();
80 + this.Context.ExpectedOutputType = this.OutputType;
81 + this.Context.Intermediates = this.Intermediates.Union(this.Libraries).ToList();
82 + this.Context.TupleDefinitionCreator = creator;
83
84 var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList();
85
86 // Add sections from the extensions with data.
71 - foreach (var data in context.ExtensionData)
87 + foreach (var data in this.Context.ExtensionData)
88 {
73 - var library = data.GetLibrary(context.TupleDefinitionCreator);
89 + var library = data.GetLibrary(this.Context.TupleDefinitionCreator);
90
91 if (library != null)
92 {
src/WixToolset.Core/Preprocessor.cs
+91 -45
@@ -14,6 +14,7 @@ namespace WixToolset.Core
14 using WixToolset.Extensibility;
15 using WixToolset.Core.Preprocess;
16 using WixToolset.Extensibility.Services;
17 + using System.Linq;
18
19 /// <summary>
20 /// Preprocessor object
@@ -35,6 +36,21 @@ namespace WixToolset.Core
36 XmlResolver = null,
37 };
38
39 + public Preprocessor(IServiceProvider serviceProvider)
40 + {
41 + this.ServiceProvider = serviceProvider;
42 + }
43 +
44 + public IEnumerable<string> IncludeSearchPaths { get; set; }
45 +
46 + public Platform Platform { get; set; }
47 +
48 + public string SourcePath { get; set; }
49 +
50 + public IDictionary<string, string> Variables { get; set; }
51 +
52 + private IServiceProvider ServiceProvider { get; }
53 +
54 private IPreprocessContext Context { get; set; }
55
56 private Stack<string> CurrentFileStack { get; } = new Stack<string>();
@@ -87,14 +103,19 @@ namespace WixToolset.Core
103 /// </summary>
104 /// <param name="context">The preprocessing context.</param>
105 /// <returns>XDocument with the postprocessed data.</returns>
90 - public XDocument Process(IPreprocessContext context)
106 + public XDocument Execute()
107 {
92 - this.Context = context ?? throw new ArgumentNullException(nameof(context));
108 + this.Context = this.CreateContext();
109 +
110 + this.PreProcess();
111
94 - using (XmlReader reader = XmlReader.Create(context.SourceFile, DocumentXmlReaderSettings))
112 + XDocument document;
113 + using (XmlReader reader = XmlReader.Create(this.Context.SourceFile, DocumentXmlReaderSettings))
114 {
96 - return Process(context, reader);
115 + document = this.Process(reader);
116 }
117 +
118 + return PostProcess(document);
119 }
120
121 /// <summary>
@@ -103,46 +124,32 @@ namespace WixToolset.Core
124 /// <param name="context">The preprocessing context.</param>
125 /// <param name="reader">XmlReader to processing the context.</param>
126 /// <returns>XDocument with the postprocessed data.</returns>
106 - public XDocument Process(IPreprocessContext context, XmlReader reader)
127 + public XDocument Execute(XmlReader reader)
128 {
108 - if (this.Context == null)
109 - {
110 - this.Context = context ?? throw new ArgumentNullException(nameof(context));
111 - }
112 - else if (this.Context != context)
113 - {
114 - throw new ArgumentException(nameof(context));
115 - }
116 -
117 - if (String.IsNullOrEmpty(this.Context.SourceFile) && !String.IsNullOrEmpty(reader.BaseURI))
129 + if (String.IsNullOrEmpty(this.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI))
130 {
131 var uri = new Uri(reader.BaseURI);
120 - this.Context.SourceFile = uri.AbsolutePath;
132 + this.SourcePath = uri.AbsolutePath;
133 }
134
123 - this.Context.CurrentSourceLineNumber = new SourceLineNumber(this.Context.SourceFile);
135 + this.Context = this.CreateContext();
136
125 - this.Helper = this.Context.ServiceProvider.GetService<IPreprocessHelper>();
137 + this.PreProcess();
138
127 - foreach (var extension in this.Context.Extensions)
128 - {
129 - if (null != extension.Prefixes)
130 - {
131 - foreach (string prefix in extension.Prefixes)
132 - {
133 - if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension))
134 - {
135 - this.ExtensionsByPrefix.Add(prefix, extension);
136 - }
137 - else
138 - {
139 - this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString()));
140 - }
141 - }
142 - }
139 + var document = this.Process(reader);
140
144 - extension.PrePreprocess(context);
145 - }
141 + return PostProcess(document);
142 + }
143 +
144 + /// <summary>
145 + /// Preprocesses a file.
146 + /// </summary>
147 + /// <param name="context">The preprocessing context.</param>
148 + /// <param name="reader">XmlReader to processing the context.</param>
149 + /// <returns>XDocument with the postprocessed data.</returns>
150 + private XDocument Process(XmlReader reader)
151 + {
152 + this.Helper = this.ServiceProvider.GetService<IPreprocessHelper>();
153
154 this.CurrentFileStack.Clear();
155 this.CurrentFileStack.Push(this.Helper.GetVariableValue(this.Context, "sys", "SOURCEFILEDIR"));
@@ -161,14 +168,6 @@ namespace WixToolset.Core
168 this.UpdateCurrentLineNumber(reader, 0);
169 throw new WixException(ErrorMessages.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message));
170 }
164 - finally
165 - {
166 - // Finalize the preprocessing.
167 - foreach (var extension in this.Context.Extensions)
168 - {
169 - extension.PostPreprocess(output);
170 - }
171 - }
171
172 return this.Context.Messaging.EncounteredError ? null : output;
173 }
@@ -1404,7 +1403,7 @@ namespace WixToolset.Core
1403 {
1404 // build a string to test the directory containing the source file first
1405 var currentFolder = this.CurrentFileStack.Peek();
1407 - var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder) , includePath);
1406 + var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder), includePath);
1407
1408 // test the source file directory
1409 if (File.Exists(includeTestPath))
@@ -1428,5 +1427,52 @@ namespace WixToolset.Core
1427
1428 return finalIncludePath;
1429 }
1430 +
1431 + private IPreprocessContext CreateContext()
1432 + {
1433 + var context = this.ServiceProvider.GetService<IPreprocessContext>();
1434 + context.Messaging = this.ServiceProvider.GetService<IMessaging>();
1435 + context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<IPreprocessorExtension>();
1436 + context.CurrentSourceLineNumber = new SourceLineNumber(this.SourcePath);
1437 + context.Platform = this.Platform;
1438 + context.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List<string>();
1439 + context.SourceFile = this.SourcePath;
1440 + context.Variables = new Dictionary<string, string>(this.Variables);
1441 +
1442 + return context;
1443 + }
1444 +
1445 + private void PreProcess()
1446 + {
1447 + foreach (var extension in this.Context.Extensions)
1448 + {
1449 + if (extension.Prefixes != null)
1450 + {
1451 + foreach (var prefix in extension.Prefixes)
1452 + {
1453 + if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension))
1454 + {
1455 + this.ExtensionsByPrefix.Add(prefix, extension);
1456 + }
1457 + else
1458 + {
1459 + this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString()));
1460 + }
1461 + }
1462 + }
1463 +
1464 + extension.PrePreprocess(this.Context);
1465 + }
1466 + }
1467 +
1468 + private XDocument PostProcess(XDocument document)
1469 + {
1470 + foreach (var extension in this.Context.Extensions)
1471 + {
1472 + extension.PostPreprocess(document);
1473 + }
1474 +
1475 + return document;
1476 + }
1477 }
1478 }
src/WixToolset.Core/WixToolsetServiceProvider.cs
+51 -77
@@ -3,6 +3,7 @@
3 namespace WixToolset.Core
4 {
5 using System;
6 + using System.Collections.Generic;
7 using WixToolset.Core.CommandLine;
8 using WixToolset.Core.ExtensibilityServices;
9 using WixToolset.Data;
@@ -11,95 +12,68 @@ namespace WixToolset.Core
12
13 public class WixToolsetServiceProvider : IServiceProvider
14 {
14 - private ExtensionManager extensionManager;
15 - private Messaging messaging;
16 - private ParseHelper parseHelper;
17 - private PreprocessHelper preprocessHelper;
18 - private TupleDefinitionCreator tupleDefinitionCreator;
19 - private WindowsInstallerBackendHelper windowsInstallerBackendHelper;
20 -
21 - public object GetService(Type serviceType)
15 + public WixToolsetServiceProvider()
16 {
23 - if (serviceType == null) throw new ArgumentNullException(nameof(serviceType));
24 -
25 - // Transients.
26 - if (serviceType == typeof(IPreprocessContext))
27 - {
28 - return new PreprocessContext(this);
29 - }
30 -
31 - if (serviceType == typeof(ICompileContext))
32 - {
33 - return new CompileContext(this);
34 - }
35 -
36 - if (serviceType == typeof(ILinkContext))
37 - {
38 - return new LinkContext(this);
39 - }
40 -
41 - if (serviceType == typeof(IBindContext))
42 - {
43 - return new BindContext(this);
44 - }
45 -
46 - if (serviceType == typeof(ILayoutContext))
47 - {
48 - return new LayoutContext(this);
49 - }
50 -
51 - if (serviceType == typeof(IResolveContext))
52 - {
53 - return new ResolveContext(this);
54 - }
55 -
56 - if (serviceType == typeof(IInscribeContext))
57 - {
58 - return new InscribeContext(this);
59 - }
60 -
61 - if (serviceType == typeof(ICommandLineContext))
17 + this.CreationFunctions = new Dictionary<Type, Func<IServiceProvider, Dictionary<Type, object>, object>>
18 {
63 - return new CommandLineContext(this);
64 - }
19 + // Singletons.
20 + { typeof(IExtensionManager), (provider, singletons) => AddSingleton(singletons, typeof(IExtensionManager), new ExtensionManager()) },
21 + { typeof(IMessaging), (provider, singletons) => AddSingleton(singletons, typeof(IMessaging), new Messaging()) },
22 + { typeof(ITupleDefinitionCreator), (provider, singletons) => AddSingleton(singletons, typeof(ITupleDefinitionCreator), new TupleDefinitionCreator(provider)) },
23 + { typeof(IParseHelper), (provider, singletons) => AddSingleton(singletons, typeof(IParseHelper), new ParseHelper(provider)) },
24 + { typeof(IPreprocessHelper), (provider, singletons) => AddSingleton(singletons, typeof(IPreprocessHelper), new PreprocessHelper(provider)) },
25 + { typeof(IWindowsInstallerBackendHelper), (provider, singletons) => AddSingleton(singletons, typeof(IWindowsInstallerBackendHelper), new WindowsInstallerBackendHelper(provider)) },
26
66 - if (serviceType == typeof(ICommandLine))
67 - {
68 - return new CommandLineParser();
69 - }
27 + // Transients.
28 + { typeof(ICommandLineContext), (provider, singletons) => new CommandLineContext(provider) },
29 + { typeof(ICommandLine), (provider, singletons) => new CommandLineParser() },
30 + { typeof(IPreprocessContext), (provider, singletons) => new PreprocessContext(provider) },
31 + { typeof(ICompileContext), (provider, singletons) => new CompileContext(provider) },
32 + { typeof(ILinkContext), (provider, singletons) => new LinkContext(provider) },
33 + { typeof(IResolveContext), (provider, singletons) => new ResolveContext(provider) },
34 + { typeof(IBindContext), (provider, singletons) => new BindContext(provider) },
35 + { typeof(ILayoutContext), (provider, singletons) => new LayoutContext(provider) },
36 + { typeof(IInscribeContext), (provider, singletons) => new InscribeContext(provider) },
37 + };
38 +
39 + this.Singletons = new Dictionary<Type, object>();
40 + }
41
71 - // Singletons.
72 - if (serviceType == typeof(IExtensionManager))
73 - {
74 - return this.extensionManager = this.extensionManager ?? new ExtensionManager();
75 - }
42 + private Dictionary<Type, Func<IServiceProvider, Dictionary<Type, object>, object>> CreationFunctions { get; }
43
77 - if (serviceType == typeof(IMessaging))
78 - {
79 - return this.messaging = this.messaging ?? new Messaging();
80 - }
44 + private Dictionary<Type, object> Singletons { get; }
45
82 - if (serviceType == typeof(ITupleDefinitionCreator))
83 - {
84 - return this.tupleDefinitionCreator = this.tupleDefinitionCreator ?? new TupleDefinitionCreator(this);
85 - }
46 + public object GetService(Type serviceType)
47 + {
48 + if (serviceType == null) throw new ArgumentNullException(nameof(serviceType));
49
87 - if (serviceType == typeof(IParseHelper))
50 + if (!this.Singletons.TryGetValue(serviceType, out var service))
51 {
89 - return this.parseHelper = this.parseHelper ?? new ParseHelper(this);
52 + if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction))
53 + {
54 + service = creationFunction(this, this.Singletons);
55 +
56 +#if DEBUG
57 + if (!serviceType.IsAssignableFrom(service?.GetType()))
58 + {
59 + throw new InvalidOperationException($"Creation function for service type: {serviceType.Name} created incompatible service with type: {service?.GetType()}");
60 + }
61 +#endif
62 + }
63 }
64
92 - if (serviceType == typeof(IPreprocessHelper))
93 - {
94 - return this.preprocessHelper = this.preprocessHelper ?? new PreprocessHelper(this);
95 - }
65 + return service ?? throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType));
66 + }
67
97 - if (serviceType == typeof(IWindowsInstallerBackendHelper))
98 - {
99 - return this.windowsInstallerBackendHelper = this.windowsInstallerBackendHelper ?? new WindowsInstallerBackendHelper(this);
100 - }
68 + public void AddService(Type serviceType, Func<IServiceProvider, Dictionary<Type, object>, object> creationFunction)
69 + {
70 + this.CreationFunctions[serviceType] = creationFunction;
71 + }
72
102 - throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType));
73 + private static object AddSingleton(Dictionary<Type, object> singletons, Type type, object service)
74 + {
75 + singletons.Add(type, service);
76 + return service;
77 }
78 }
79 }