Переглянути джерело

Refactoring of binding and argument handling and console logging

Lukas Angerer 4 роки тому
батько
коміт
9c43c377ce

+ 27 - 0
CustomHostingDemo/CommandContextParameter.cs

@@ -0,0 +1,27 @@
+using Ninject.Activation;
+using Ninject.Parameters;
+using System;
+using System.CommandLine.Invocation;
+using System.Linq;
+
+namespace CustomHostingDemo
+{
+    public class CommandContextParameter : Parameter
+    {
+        public InvocationContext Context { get; }
+        public IDefaultArgs Args { get; set; }
+
+        public CommandContextParameter(InvocationContext context, IDefaultArgs args)
+            : base(nameof(CommandContextParameter), context, shouldInherit: true)
+        {
+            Context = context;
+            Args = args;
+        }
+
+        public static CommandContextParameter FromContext(IContext context)
+        {
+            return context.Parameters.OfType<CommandContextParameter>().FirstOrDefault()
+                ?? throw new Exception("Cannot resolve InvocationContext outside of the scope of an invocation");
+        }
+    }
+}

+ 14 - 0
CustomHostingDemo/CommandHandlerModule.cs

@@ -0,0 +1,14 @@
+using Ninject.Modules;
+using System.CommandLine.Invocation;
+
+namespace CustomHostingDemo
+{
+    public class CommandHandlerModule : NinjectModule
+    {
+        public override void Load()
+        {
+            Bind<InvocationContext>().ToMethod(ctx => CommandContextParameter.FromContext(ctx).Context);
+            Bind<IDefaultArgs>().ToMethod(ctx => CommandContextParameter.FromContext(ctx).Args);
+        }
+    }
+}

+ 11 - 30
CustomHostingDemo/HelloCommand.cs

@@ -1,9 +1,8 @@
-using Microsoft.Extensions.Logging;
+using CustomHostingDemo.Logging;
+using Microsoft.Extensions.Configuration;
 using System;
 using System.CommandLine;
 using System.CommandLine.Invocation;
-using System.CommandLine.IO;
-using System.CommandLine.Rendering;
 using System.Threading.Tasks;
 
 namespace CustomHostingDemo
@@ -17,7 +16,7 @@ namespace CustomHostingDemo
             AddOption(new Option<bool>("--verbose"));
         }
 
-        public class HelloArgs
+        public class HelloArgs : IDefaultArgs
         {
             public DateTime Date { get; set; }
             public bool Verbose { get; set; }
@@ -25,40 +24,22 @@ namespace CustomHostingDemo
 
         public class DefaultHandler : ICommandHandler<HelloArgs>
         {
-            private readonly ILogger _logger;
-            private readonly ILog _log;
+            private readonly ICliLogger _logger;
+            private readonly IConfiguration _config;
 
-            public DefaultHandler(Logger<DefaultHandler> logger, ILog log)
+            public DefaultHandler(ICliLogger logger, IConfiguration config)
             {
                 _logger = logger;
-                _log = log;
+                _config = config;
             }
 
             public Task<int> InvokeAsync(InvocationContext context, HelloArgs args)
             {
-                _log.LogMessage("Hello YOU!");
-                _log.LogMessage($"P: --date {args.Date}");
-                _log.LogMessage($"P: --verbose {args.Verbose}");
+                _logger.LogContent($"Hello {_config["Hello"]}! How are you?");
+                _logger.LogInfo($"P: --date {args.Date}");
+                _logger.LogInfo($"P: --verbose {args.Verbose}");
 
-                _logger.LogInformation("INFO from DefaultHandler");
-
-                var span = new ContainerSpan(StyleSpan.UnderlinedOn(),
-                              new ContentSpan("Underlining"),
-                              StyleSpan.UnderlinedOff());
-
-                context.Console.Out.WriteLine(span.ToString(OutputMode.Auto));
-
-                context.Console.Out.WriteLine(new ContainerSpan(
-                    ForegroundColorSpan.LightGreen(),
-                    StyleSpan.BlinkOn(),
-                    new ContentSpan("Blinking"),
-                    StyleSpan.BlinkOff(),
-                    new ContentSpan("Noblink"),
-                    ForegroundColorSpan.Reset(),
-                    new ContentSpan("Normal")
-                ).ToString(OutputMode.Ansi));
-
-                return Task.FromResult(3);
+                return Task.FromResult(0);
             }
         }
     }

+ 13 - 0
CustomHostingDemo/IDefaultArgs.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CustomHostingDemo
+{
+    public interface IDefaultArgs
+    {
+        bool Verbose { get; }
+    }
+}

+ 0 - 36
CustomHostingDemo/ILog.cs

@@ -1,36 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.CommandLine;
-using System.CommandLine.Invocation;
-using System.CommandLine.IO;
-using System.CommandLine.Rendering;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace CustomHostingDemo
-{
-    public interface ILog
-    {
-        void LogMessage(string msg);
-    }
-
-    public class Log : ILog
-    {
-        private readonly IConsole _console;
-
-        public Log(InvocationContext context)
-        {
-            _console = context.Console;
-        }
-
-        public void LogMessage(string msg)
-        {
-            _console.Out.WriteLine(new ContainerSpan(
-                ForegroundColorSpan.LightBlue(),
-                new ContentSpan(msg),
-                ForegroundColorSpan.Reset()
-            ).ToString(OutputMode.Ansi));
-        }
-    }
-}

+ 65 - 0
CustomHostingDemo/Logging/CliLogger.cs

@@ -0,0 +1,65 @@
+using System.CommandLine;
+using System.CommandLine.Invocation;
+using System.CommandLine.IO;
+using System.CommandLine.Rendering;
+
+namespace CustomHostingDemo.Logging
+{
+    public class CliLogger : ICliLogger
+    {
+        private readonly IConsole _console;
+        private readonly IDefaultArgs _args;
+
+        public CliLogger(InvocationContext context, IDefaultArgs args)
+        {
+            _console = context.Console;
+            _args = args;
+        }
+
+        public ICliLogger LogContent(string message)
+        {
+            return Log(new ContentSpan(message));
+        }
+
+        public ICliLogger LogError(string message)
+        {
+            return Log(new ContainerSpan(
+                ForegroundColorSpan.Red(),
+                new ContentSpan("[ERROR] "),
+                new ContentSpan(message),
+                ForegroundColorSpan.Reset()
+            ));
+        }
+
+        public ICliLogger LogInfo(string message)
+        {
+            if (!_args.Verbose)
+            {
+                return this;
+            }
+
+            return Log(new ContainerSpan(
+                ForegroundColorSpan.LightGray(),
+                new ContentSpan("[INFO] "),
+                new ContentSpan(message),
+                ForegroundColorSpan.Reset()
+            ));
+        }
+
+        public ICliLogger LogWarning(string message)
+        {
+            return Log(new ContainerSpan(
+                ForegroundColorSpan.Yellow(),
+                new ContentSpan("[WARN] "),
+                new ContentSpan(message),
+                ForegroundColorSpan.Reset()
+            ));
+        }
+
+        private ICliLogger Log(TextSpan span)
+        {
+            _console.Out.WriteLine(span.ToString(OutputMode.Ansi));
+            return this;
+        }
+    }
+}

+ 10 - 0
CustomHostingDemo/Logging/ICliLogger.cs

@@ -0,0 +1,10 @@
+namespace CustomHostingDemo.Logging
+{
+    public interface ICliLogger
+    {
+        ICliLogger LogInfo(string message);
+        ICliLogger LogContent(string message);
+        ICliLogger LogWarning(string message);
+        ICliLogger LogError(string message);
+    }
+}

+ 17 - 0
CustomHostingDemo/Logging/LoggingModule.cs

@@ -0,0 +1,17 @@
+using Microsoft.Extensions.Logging;
+using Ninject.Modules;
+
+namespace CustomHostingDemo.Logging
+{
+    public class LoggingModule : NinjectModule
+    {
+        public override void Load()
+        {
+            Bind<ILoggerFactory>().To<LoggerFactory>().InSingletonScope();
+            Bind(typeof(Logger<>)).ToSelf().InSingletonScope();
+            Bind<ILoggerProvider>().To<LoggerProvider>().InSingletonScope();
+
+            Bind<ICliLogger>().To<CliLogger>();
+        }
+    }
+}

+ 4 - 1
CustomHostingDemo/NinjectCommandHandler.cs

@@ -3,6 +3,7 @@ using Ninject.Parameters;
 using System;
 using System.CommandLine.Binding;
 using System.CommandLine.Invocation;
+using System.Linq;
 using System.Threading.Tasks;
 
 namespace CustomHostingDemo
@@ -34,8 +35,10 @@ namespace CustomHostingDemo
             var binder = new ModelBinder<TArg>();
             binder.UpdateInstance(cmdArgs, context.BindingContext);
 
-            var handler = (ICommandHandler<TArg>)_kernel.Get(_handlerType, new Parameter(nameof(InvocationContext), context, shouldInherit: true));
+            var handler = (ICommandHandler<TArg>)_kernel.Get(_handlerType, new CommandContextParameter(context, cmdArgs as IDefaultArgs));
             return handler.InvokeAsync(context, cmdArgs);
         }
+
+        
     }
 }

+ 5 - 38
CustomHostingDemo/Program.cs

@@ -2,15 +2,11 @@
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
 using Ninject;
-using Ninject.Syntax;
 using System;
 using System.CommandLine;
-using System.CommandLine.Binding;
 using System.CommandLine.Builder;
-using System.CommandLine.Invocation;
 using System.CommandLine.Parsing;
 using System.IO;
-using System.Linq;
 using System.Reflection;
 
 namespace CustomHostingDemo
@@ -19,7 +15,10 @@ namespace CustomHostingDemo
     {
         static int Main(string[] args)
         {
-            var kernel = new StandardKernel();
+            var kernel = new StandardKernel(
+                new LoggingModule(),
+                new CommandHandlerModule()
+            );
 
             var config = new ConfigurationBuilder()
                 .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
@@ -28,26 +27,9 @@ namespace CustomHostingDemo
                 .Build();
 
             kernel.Bind<IConfiguration>().ToConstant(config).InSingletonScope();
-            kernel.Bind<ILoggerFactory>().To<LoggerFactory>().InSingletonScope();
-            kernel.Bind(typeof(Logger<>)).ToSelf().InSingletonScope();
-            kernel.Bind<ILoggerProvider>().To<LoggerProvider>().InSingletonScope();
-            kernel.Bind<ILog>().To<Log>().InTransientScope();
-
-            kernel.Bind<InvocationContext>().ToMethod(ctx =>
-            {
-                var parameter = ctx.Parameters.FirstOrDefault(p => p.Name == nameof(InvocationContext));
-                if (parameter == null)
-                {
-                    throw new Exception("Cannot resolve InvocationContext outside of an actual NinjectCommandHandler invocation");
-                }
-
-                return (InvocationContext)parameter.GetValue(ctx, null);
-            });
-
-            Console.WriteLine($"Hello {config["Hello"]}");
 
             var logger = kernel.Get<Logger<Program>>();
-            logger.LogInformation("Informational Message");
+            logger.LogInformation($"Informational Message - Hello {config["Hello"]}");
             logger.LogWarning("Ooopsie!");
 
             var rootCommand = new RootCommand()
@@ -56,21 +38,6 @@ namespace CustomHostingDemo
             };
 
             var parser = new CommandLineBuilder(rootCommand)
-                //.UseMiddleware((invocationContext) =>
-                //{
-                //    var cmdArgs = new HelloCommand.HelloArgs();
-                //    var binder = new ModelBinder<HelloCommand.HelloArgs>();
-                //    binder.UpdateInstance(cmdArgs, invocationContext.BindingContext);
-
-                //    kernel.Bind<HelloCommand.HelloArgs>().ToConstant(cmdArgs).InSingletonScope();
-
-                //    //invocationContext.BindingContext.AddService(typeof(HelloCommand.HelloArgs), () => cmdArgs);
-                //    invocationContext.BindingContext.AddService(typeof(HelloCommand.DefaultHandler), () =>
-                //    {
-                //        var handler = kernel.Get<HelloCommand.DefaultHandler>();
-                //        return handler;
-                //    });
-                //})
                 .UseDefaults()
                 .Build();