// 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. namespace WixToolset.Core { using System; using System.Collections.Generic; using WixToolset.Core.CommandLine; using WixToolset.Core.ExtensibilityServices; using WixToolset.Data; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; public sealed class WixToolsetServiceProvider : IServiceProvider { public WixToolsetServiceProvider() { this.CreationFunctions = new Dictionary, object>>(); this.Singletons = new Dictionary(); // Singletons. this.AddService((provider, singletons) => AddSingleton(singletons, new ExtensionManager(provider))); this.AddService((provider, singletons) => AddSingleton(singletons, new Messaging())); this.AddService((provider, singletons) => AddSingleton(singletons, new TupleDefinitionCreator(provider))); this.AddService((provider, singletons) => AddSingleton(singletons, new ParseHelper(provider))); this.AddService((provider, singletons) => AddSingleton(singletons, new PreprocessHelper(provider))); this.AddService((provider, singletons) => AddSingleton(singletons, new BackendHelper(provider))); this.AddService((provider, singletons) => AddSingleton(singletons, new WindowsInstallerBackendHelper(provider))); // Transients. this.AddService((provider, singletons) => new CommandLineArguments(provider)); this.AddService((provider, singletons) => new CommandLineContext(provider)); this.AddService((provider, singletons) => new CommandLine.CommandLine(provider)); this.AddService((provider, singletons) => new PreprocessContext(provider)); this.AddService((provider, singletons) => new CompileContext(provider)); this.AddService((provider, singletons) => new LibraryContext(provider)); this.AddService((provider, singletons) => new LinkContext(provider)); this.AddService((provider, singletons) => new ResolveContext(provider)); this.AddService((provider, singletons) => new BindContext(provider)); this.AddService((provider, singletons) => new DecompileContext(provider)); this.AddService((provider, singletons) => new LayoutContext(provider)); this.AddService((provider, singletons) => new InscribeContext(provider)); this.AddService((provider, singletons) => new Binder(provider)); this.AddService((provider, singletons) => new Compiler(provider)); this.AddService((provider, singletons) => new Decompiler(provider)); this.AddService((provider, singletons) => new LayoutCreator(provider)); this.AddService((provider, singletons) => new Preprocessor(provider)); this.AddService((provider, singletons) => new Librarian(provider)); this.AddService((provider, singletons) => new Linker(provider)); this.AddService((provider, singletons) => new Resolver(provider)); // Internal implementations. this.AddService((provider, singletons) => new Localizer(provider)); } private Dictionary, object>> CreationFunctions { get; } private Dictionary Singletons { get; } public bool TryGetService(Type serviceType, out object service) { if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); if (!this.Singletons.TryGetValue(serviceType, out service)) { if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction)) { service = creationFunction(this, this.Singletons); #if DEBUG if (!serviceType.IsAssignableFrom(service?.GetType())) { throw new InvalidOperationException($"Creation function for service type: {serviceType.Name} created incompatible service with type: {service?.GetType()}"); } #endif } } return service != null; } public object GetService(Type serviceType) { return this.TryGetService(serviceType, out var service) ? service : throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType)); } public void AddService(Type serviceType, Func, object> creationFunction) { this.CreationFunctions[serviceType] = creationFunction; } public void AddService(Func, T> creationFunction) where T : class { this.AddService(typeof(T), creationFunction); } private static T AddSingleton(Dictionary singletons, T service) where T : class { singletons.Add(typeof(T), service); return service; } } }