Add more general purpose service provider to CommandProcessor.
authorMike McLaughlin <mikem@microsoft.com>
Sat, 16 Mar 2019 00:10:51 +0000 (17:10 -0700)
committerMike McLaughlin <mikem@microsoft.com>
Wed, 20 Mar 2019 00:35:51 +0000 (17:35 -0700)
Add the "ConsoleProvider" instance as a service. Change the "exit"
command to use it.

src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs
src/Tools/dotnet-dump/AnalyzeContext.cs
src/Tools/dotnet-dump/Analyzer.cs
src/Tools/dotnet-dump/Commands/ExitCommand.cs

index 5d42b35c93d63e2166f36c69fc989c4123a67391..a7b2dbe62b827bcaa0e611a2e3bbfd3a8df6b7ce 100644 (file)
@@ -19,11 +19,7 @@ namespace Microsoft.Diagnostic.Repl
     {
         private readonly Parser _parser;
         private readonly Command _rootCommand;
-
-        /// <summary>
-        /// Domain specific context passed to commands
-        /// </summary>
-        public object CommandContext { get; set; }
+        private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
 
         /// <summary>
         /// Create an instance of the command processor;
@@ -31,6 +27,7 @@ namespace Microsoft.Diagnostic.Repl
         /// <param name="assemblies">The list of assemblies to look for commands</param>
         public CommandProcessor(IEnumerable<Assembly> assemblies)
         {
+            _services.Add(typeof(CommandProcessor), this);
             var rootBuilder = new CommandLineBuilder();
             rootBuilder.UseHelp()
                        .UseParseDirective()
@@ -42,6 +39,26 @@ namespace Microsoft.Diagnostic.Repl
             _parser = rootBuilder.Build();
         }
 
+        /// <summary>
+        /// Adds a service or context to inject into an command.
+        /// </summary>
+        /// <typeparam name="T">type of service</typeparam>
+        /// <param name="instance">service instance</param>
+        public void AddService<T>(T instance)
+        {
+            AddService(typeof(T), instance);
+        }
+
+        /// <summary>
+        /// Adds a service or context to inject into an command.
+        /// </summary>
+        /// <param name="type">service type</param>
+        /// <param name="instance">service instance</param>
+        public void AddService(Type type, object instance)
+        {
+            _services.Add(type, instance);
+        }
+
         /// <summary>
         /// Parse the command line.
         /// </summary>
@@ -194,7 +211,7 @@ namespace Microsoft.Diagnostic.Repl
             {
                 IEnumerable<OptionResult> optionResults = context.ParseResult.CommandResult.Children.OfType<OptionResult>();
 
-                foreach (var property in _properties)
+                foreach ((PropertyInfo Property, Option Option) property in _properties)
                 {
                     object value = property.Property.GetValue(instance);
 
@@ -210,11 +227,8 @@ namespace Microsoft.Diagnostic.Repl
                         else if (propertyType == typeof(IConsole)) {
                             value = context.Console;
                         }
-                        else if (propertyType == typeof(CommandProcessor)) {
-                            value = _commandProcessor;
-                        }
-                        else if (propertyType == _commandProcessor.CommandContext?.GetType()) {
-                            value = _commandProcessor.CommandContext;
+                        else if (_commandProcessor._services.TryGetValue(propertyType, out object service)) {
+                            value = service;
                         }
                         else if (property.Option != null)
                         {
index 9fff5af27838cf2865d9095bcfa8b0f5fde9f448..d347a0e25f7de140d954181914f5866a06d2d5bc 100644 (file)
@@ -20,11 +20,10 @@ namespace Microsoft.Diagnostic.Tools.Dump
         private ClrRuntime _runtime;
         private SOSHost _sosHost;
 
-        public AnalyzeContext(IConsole console, DataTarget target, Action exit)
+        public AnalyzeContext(IConsole console, DataTarget target)
         {
             _console = console;
             Target = target;
-            Exit = exit;
         }
 
         /// <summary>
index 69939f3b7c125cd0498b8bec24a43afe8e17c21b..be033bd99ab5f7fc10291cae1c0133c7ebf69033 100644 (file)
@@ -20,6 +20,7 @@ namespace Microsoft.Diagnostic.Tools.Dump
         {
             _consoleProvider = new ConsoleProvider();
             _commandProcessor = new CommandProcessor(new Assembly[] { typeof(Analyzer).Assembly });
+            _commandProcessor.AddService(_consoleProvider);
         }
 
         public async Task<int> Analyze(FileInfo dump_path, string[] command)
@@ -45,10 +46,10 @@ namespace Microsoft.Diagnostic.Tools.Dump
                     _consoleProvider.Out.WriteLine("Type 'quit' or 'exit' to exit the session.");
 
                     // Create common analyze context for commands
-                    var analyzeContext = new AnalyzeContext(_consoleProvider, target, _consoleProvider.Stop) {
+                    var analyzeContext = new AnalyzeContext(_consoleProvider, target) {
                         CurrentThreadId = unchecked((int)target.DataReader.EnumerateAllThreads().FirstOrDefault())
                     };
-                    _commandProcessor.CommandContext = analyzeContext;
+                    _commandProcessor.AddService(analyzeContext);
 
                     // Automatically enable symbol server support on Linux and MacOS
                     if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
index a9fe36a4194a8be5fb6f615881a27e0dc26209fb..716d3e38ce1b2455559e5047e5d9ad18e22c3844 100644 (file)
@@ -9,11 +9,11 @@ namespace Microsoft.Diagnostic.Tools.Dump
     [CommandAlias(Name = "quit")]
     public class ExitCommand : CommandBase
     {
-        public AnalyzeContext AnalyzeContext { get; set; }
+        public ConsoleProvider ConsoleProvider { get; set; }
 
         public override Task InvokeAsync()
         {
-            AnalyzeContext.Exit();
+            ConsoleProvider.Stop();
             return Task.CompletedTask;
         }
     }