| 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.Core |
| 4 | { |
| 5 | using System; |
| 6 | using System.Collections.Generic; |
| 7 | using WixToolset.Core.CommandLine; |
| 8 | using WixToolset.Core.ExtensibilityServices; |
| 9 | using WixToolset.Data; |
| 10 | using WixToolset.Extensibility.Data; |
| 11 | using WixToolset.Extensibility.Services; |
| 12 | |
| 13 | internal class WixToolsetServiceProvider : IWixToolsetCoreServiceProvider |
| 14 | { |
| 15 | public WixToolsetServiceProvider() |
| 16 | { |
| 17 | this.CreationFunctions = new Dictionary<Type, Func<IWixToolsetCoreServiceProvider, Dictionary<Type, object>, object>>(); |
| 18 | this.Singletons = new Dictionary<Type, object>(); |
| 19 | |
| 20 | // Singletons. |
| 21 | this.AddService((provider, singletons) => AddSingleton<IExtensionManager>(singletons, new ExtensionManager(provider))); |
| 22 | this.AddService((provider, singletons) => AddSingleton<IMessaging>(singletons, new Messaging())); |
| 23 | this.AddService((provider, singletons) => AddSingleton<IBundleValidator>(singletons, new BundleValidator(provider))); |
| 24 | this.AddService((provider, singletons) => AddSingleton<ISymbolDefinitionCreator>(singletons, new SymbolDefinitionCreator(provider))); |
| 25 | this.AddService((provider, singletons) => AddSingleton<IParseHelper>(singletons, new ParseHelper(provider))); |
| 26 | this.AddService((provider, singletons) => AddSingleton<IPreprocessHelper>(singletons, new PreprocessHelper(provider))); |
| 27 | this.AddService((provider, singletons) => AddSingleton<ILayoutServices>(singletons, new LayoutServices(provider))); |
| 28 | this.AddService((provider, singletons) => AddSingleton<IBackendHelper>(singletons, new BackendHelper(provider))); |
| 29 | this.AddService((provider, singletons) => AddSingleton<IPathResolver>(singletons, new PathResolver())); |
| 30 | this.AddService((provider, singletons) => AddSingleton<IFileResolver>(singletons, new FileResolver())); |
| 31 | this.AddService((provider, singletons) => AddSingleton<IFileSystem>(singletons, new FileSystem())); |
| 32 | this.AddService((provider, singletons) => AddSingleton<IWixBranding>(singletons, new WixBranding())); |
| 33 | |
| 34 | // Transients. |
| 35 | this.AddService<ICommandLineArguments>((provider, singletons) => new CommandLineArguments(provider)); |
| 36 | this.AddService<ICommandLineContext>((provider, singletons) => new CommandLineContext(provider)); |
| 37 | this.AddService<ICommandLine>((provider, singletons) => new CommandLine.CommandLine(provider)); |
| 38 | this.AddService<IPreprocessContext>((provider, singletons) => new PreprocessContext(provider)); |
| 39 | this.AddService<ICompileContext>((provider, singletons) => new CompileContext(provider)); |
| 40 | this.AddService<IOptimizeContext>((provider, singletons) => new OptimizeContext(provider)); |
| 41 | this.AddService<ILibraryContext>((provider, singletons) => new LibraryContext(provider)); |
| 42 | this.AddService<ILibraryResult>((provider, singletons) => new LibraryResult()); |
| 43 | this.AddService<ILinkContext>((provider, singletons) => new LinkContext(provider)); |
| 44 | this.AddService<IResolveContext>((provider, singletons) => new ResolveContext(provider)); |
| 45 | this.AddService<IBindContext>((provider, singletons) => new BindContext(provider)); |
| 46 | this.AddService<ILayoutContext>((provider, singletons) => new LayoutContext(provider)); |
| 47 | |
| 48 | this.AddService<IBindFileWithPath>((provider, singletons) => new BindFileWithPath()); |
| 49 | this.AddService<IBindPath>((provider, singletons) => new BindPath()); |
| 50 | this.AddService<IBindResult>((provider, singletons) => new BindResult()); |
| 51 | this.AddService<IComponentKeyPath>((provider, singletons) => new ComponentKeyPath()); |
| 52 | this.AddService<IIncludedFile>((provider, singletons) => new IncludedFile()); |
| 53 | this.AddService<IPreprocessResult>((provider, singletons) => new PreprocessResult()); |
| 54 | this.AddService<IResolvedDirectory>((provider, singletons) => new ResolvedDirectory()); |
| 55 | this.AddService<IResolveFileResult>((provider, singletons) => new ResolveFileResult()); |
| 56 | this.AddService<IResolveResult>((provider, singletons) => new ResolveResult()); |
| 57 | this.AddService<IResolvedCabinet>((provider, singletons) => new ResolvedCabinet()); |
| 58 | this.AddService<IVariableResolution>((provider, singletons) => new VariableResolution()); |
| 59 | |
| 60 | this.AddService<IBinder>((provider, singletons) => new Binder(provider)); |
| 61 | this.AddService<ICompiler>((provider, singletons) => new Compiler(provider)); |
| 62 | this.AddService<IOptimizer>((provider, singletons) => new Optimizer(provider)); |
| 63 | this.AddService<ILayoutCreator>((provider, singletons) => new LayoutCreator(provider)); |
| 64 | this.AddService<IPreprocessor>((provider, singletons) => new Preprocessor(provider)); |
| 65 | this.AddService<ILibrarian>((provider, singletons) => new Librarian(provider)); |
| 66 | this.AddService<ILinker>((provider, singletons) => new Linker(provider)); |
| 67 | this.AddService<IResolver>((provider, singletons) => new Resolver(provider)); |
| 68 | |
| 69 | this.AddService<ILocalizationParser>((provider, singletons) => new LocalizationParser(provider)); |
| 70 | this.AddService<IVariableResolver>((provider, singletons) => new VariableResolver(provider)); |
| 71 | } |
| 72 | |
| 73 | private Dictionary<Type, Func<IWixToolsetCoreServiceProvider, Dictionary<Type, object>, object>> CreationFunctions { get; } |
| 74 | |
| 75 | private Dictionary<Type, object> Singletons { get; } |
| 76 | |
| 77 | public object GetService(Type serviceType) |
| 78 | { |
| 79 | if (serviceType == null) |
| 80 | { |
| 81 | throw new ArgumentNullException(nameof(serviceType)); |
| 82 | } |
| 83 | |
| 84 | if (!this.Singletons.TryGetValue(serviceType, out var service)) |
| 85 | { |
| 86 | if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction)) |
| 87 | { |
| 88 | service = creationFunction(this, this.Singletons); |
| 89 | |
| 90 | #if DEBUG |
| 91 | if (!serviceType.IsAssignableFrom(service?.GetType())) |
| 92 | { |
| 93 | throw new InvalidOperationException($"Creation function for service type: {serviceType.Name} created incompatible service with type: {service?.GetType()}"); |
| 94 | } |
| 95 | #endif |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | return service; |
| 100 | } |
| 101 | |
| 102 | public void AddService(Type serviceType, Func<IWixToolsetCoreServiceProvider, Dictionary<Type, object>, object> creationFunction) |
| 103 | { |
| 104 | this.CreationFunctions[serviceType] = creationFunction; |
| 105 | } |
| 106 | |
| 107 | public void AddService<T>(Func<IWixToolsetCoreServiceProvider, Dictionary<Type, object>, T> creationFunction) where T : class |
| 108 | { |
| 109 | this.AddService(typeof(T), creationFunction); |
| 110 | } |
| 111 | |
| 112 | private static T AddSingleton<T>(Dictionary<Type, object> singletons, T service) where T : class |
| 113 | { |
| 114 | singletons.Add(typeof(T), service); |
| 115 | return service; |
| 116 | } |
| 117 | } |
| 118 | } |