diff --git a/App.config b/App.config index 193aecc..45a783d 100644 --- a/App.config +++ b/App.config @@ -1,6 +1,14 @@ - + + + + + + + + + \ No newline at end of file diff --git a/CommandsExecutor.cs b/CommandExecutor/CommandsExecutor.cs similarity index 58% rename from CommandsExecutor.cs rename to CommandExecutor/CommandsExecutor.cs index 29091c9..1ce8dcd 100644 --- a/CommandsExecutor.cs +++ b/CommandExecutor/CommandsExecutor.cs @@ -1,28 +1,23 @@ -using System; -using System.Collections.Generic; +using Ninject; +using System; using System.IO; using System.Linq; namespace CommandLineTool { - /// - /// Знает про полный список команд и умеет выполнять их. - /// public class CommandsExecutor : ICommandsExecutor { - private readonly TextWriter writer; - private readonly List commands = new List(); + private TextWriter writer; + private readonly ConsoleCommand[] commands; - public CommandsExecutor(TextWriter writer) + //Атрибут [Named("error")]добавляет зависимость от Ninject контейнера, + //поэтому используйте его, если это не критично для вас. + public CommandsExecutor(ConsoleCommand[] commands, /*[Named("error")]*/TextWriter writer) { + this.commands = commands; this.writer = writer; } - public void Register(ConsoleCommand command) - { - commands.Add(command); - } - public string[] GetAvailableCommandName() { return commands.Select(c => c.Name).ToArray(); @@ -37,7 +32,7 @@ public void Execute(string[] args) { if (args[0].Length == 0) { - Console.WriteLine("Please specify as the first command line argument"); + writer.WriteLine("Please specify as the first command line argument"); return; } @@ -46,7 +41,7 @@ public void Execute(string[] args) if (cmd == null) writer.WriteLine("Sorry. Unknown command {0}", commandName); else - cmd.Execute(args, writer); + cmd.Execute(args.Skip(1).ToArray()); } } } \ No newline at end of file diff --git a/ICommandsExecutor.cs b/CommandExecutor/ICommandsExecutor.cs similarity index 74% rename from ICommandsExecutor.cs rename to CommandExecutor/ICommandsExecutor.cs index 5e80c57..016d0c8 100644 --- a/ICommandsExecutor.cs +++ b/CommandExecutor/ICommandsExecutor.cs @@ -2,6 +2,7 @@ { public interface ICommandsExecutor { + ConsoleCommand FindCommandByName(string name); string[] GetAvailableCommandName(); void Execute(string[] args); } diff --git a/CommandLineTool.csproj b/CommandLineTool.csproj index 9885ff3..8605f91 100644 --- a/CommandLineTool.csproj +++ b/CommandLineTool.csproj @@ -33,7 +33,20 @@ 4 + + packages\Castle.Core.4.2.0\lib\net45\Castle.Core.dll + + + packages\Ninject.3.3.4\lib\net45\Ninject.dll + + + packages\Ninject.Extensions.Conventions.3.3.0\lib\net45\Ninject.Extensions.Conventions.dll + + + packages\Ninject.Extensions.Factory.3.3.2\lib\net45\Ninject.Extensions.Factory.dll + + @@ -43,18 +56,22 @@ - + + - + + + + \ No newline at end of file diff --git a/Commands/ConsoleCommand.cs b/Commands/ConsoleCommand.cs index 9638ec1..0dd52b0 100644 --- a/Commands/ConsoleCommand.cs +++ b/Commands/ConsoleCommand.cs @@ -1,6 +1,4 @@ -using System.IO; - -namespace CommandLineTool +namespace CommandLineTool { public abstract class ConsoleCommand { @@ -12,6 +10,6 @@ protected ConsoleCommand(string name, string help) public string Name { get; } public string Help { get; } - public abstract void Execute(string[] args, TextWriter writer); + public abstract void Execute(string[] args); } } \ No newline at end of file diff --git a/Commands/DetailedHelpCommand.cs b/Commands/DetailedHelpCommand.cs index b556338..ad09a54 100644 --- a/Commands/DetailedHelpCommand.cs +++ b/Commands/DetailedHelpCommand.cs @@ -5,21 +5,24 @@ namespace CommandLineTool { public class DetailedHelpCommand : ConsoleCommand { - private readonly Func findCommand; + private readonly Lazy executor; + private readonly TextWriter writer; - public DetailedHelpCommand(Func findCommand) + public DetailedHelpCommand(Lazy executor, TextWriter writer) : base("help", "help # prints help for ") { - this.findCommand = findCommand; + this.executor = executor; + this.writer = writer; } - public override void Execute(string[] args, TextWriter writer) + public override void Execute(string[] args) { - var cmd = findCommand(args[1]); - if (cmd == null) - writer.WriteLine("Sorry. Unknown command {0}", args[1]); - else + var commandName = args[0]; + var cmd = executor.Value.FindCommandByName(commandName); + if (cmd != null) writer.WriteLine(cmd.Help); + else + writer.WriteLine("Not a command " + commandName); } } } \ No newline at end of file diff --git a/Commands/HelpCommand.cs b/Commands/HelpCommand.cs index c83eba7..a309a17 100644 --- a/Commands/HelpCommand.cs +++ b/Commands/HelpCommand.cs @@ -1,23 +1,23 @@ -using System.IO; +using System; +using System.IO; namespace CommandLineTool { - internal class HelpCommand : ConsoleCommand + public class HelpCommand : ConsoleCommand { - private readonly ICommandsExecutor executor; + private readonly Lazy executor; + private readonly TextWriter writer; - //Также можно еще из конструктора получать делегат и использовать его для получения команд. - //private readonly Func getAvailableCommands; - - public HelpCommand(ICommandsExecutor executor) + public HelpCommand(Lazy executor, TextWriter writer) : base("h", "h # prints available commands list") { this.executor = executor; + this.writer = writer; } - public override void Execute(string[] args, TextWriter writer) + public override void Execute(string[] args) { - writer.WriteLine("Available commands: " + string.Join(", ", executor.GetAvailableCommandName())); + writer.WriteLine("Available commands: " + string.Join(", ", executor.Value.GetAvailableCommandName())); } } } \ No newline at end of file diff --git a/Commands/PrintTimeCommand.cs b/Commands/PrintTimeCommand.cs index cc227b0..1d32143 100644 --- a/Commands/PrintTimeCommand.cs +++ b/Commands/PrintTimeCommand.cs @@ -5,11 +5,15 @@ namespace CommandLineTool { public class PrintTimeCommand : ConsoleCommand { - public PrintTimeCommand() + private readonly TextWriter writer; + + public PrintTimeCommand(TextWriter writer) : base("printtime", "printtime # prints current time") - { } + { + this.writer = writer; + } - public override void Execute(string[] args, TextWriter writer) + public override void Execute(string[] args) { writer.WriteLine(DateTime.Now); } diff --git a/Commands/TimerCommand.cs b/Commands/TimerCommand.cs index 56d0b7a..e6ea386 100644 --- a/Commands/TimerCommand.cs +++ b/Commands/TimerCommand.cs @@ -6,17 +6,21 @@ namespace CommandLineTool { public class TimerCommand : ConsoleCommand { - public TimerCommand() : base("timer", "timer # starts timer for milliseconds") - { } + private readonly TextWriter writer; - public override void Execute(string[] args, TextWriter writer) + public TimerCommand(TextWriter writer) : base("timer", "timer # starts timer for milliseconds") { - if (args.Length != 2) + this.writer = writer; + } + + public override void Execute(string[] args) + { + if (args.Length != 1) { writer.WriteLine("Error!"); return; } - var timeout = TimeSpan.FromMilliseconds(int.Parse(args[1])); + var timeout = TimeSpan.FromMilliseconds(int.Parse(args[0])); writer.WriteLine("Waiting for " + timeout); Thread.Sleep(timeout); writer.WriteLine("Done!"); diff --git a/Program.cs b/Program.cs index 34dd294..d122f69 100644 --- a/Program.cs +++ b/Program.cs @@ -1,18 +1,34 @@ using System; +using System.IO; +using Ninject; +using Ninject.Extensions.Conventions; +using Ninject.Modules; namespace CommandLineTool { + public class CommandsModule : NinjectModule + { + public override void Load() + { + Kernel.Bind(f => + { + var commandTypes = f.FromThisAssembly().Select(typeof(ConsoleCommand).IsAssignableFrom); + commandTypes.BindAllBaseClasses().Configure(c => c.InSingletonScope()); + }); + Kernel.Bind().To().InSingletonScope(); + Kernel.Bind().To() + .WhenInjectedInto().InSingletonScope(); + Kernel.Bind().To() + .WhenInjectedInto().InSingletonScope(); + } + } + public class Program { private static ICommandsExecutor CreateExecutor() { - // Этот метод — единственное место изменения, при добавлении новой команды - var executor = new CommandsExecutor(Console.Out); - executor.Register(new PrintTimeCommand()); - executor.Register(new TimerCommand()); - executor.Register(new HelpCommand(executor)); - executor.Register(new DetailedHelpCommand(executor.FindCommandByName)); - return executor; + var container = new StandardKernel(new CommandsModule()); + return container.Get(); } static void Main(string[] args) @@ -29,8 +45,7 @@ public static void RunInteractiveMode(ICommandsExecutor executor) while (true) { var line = Console.ReadLine(); - if (line == null || line == "exit") - return; + if (line == null || line == "exit") return; executor.Execute(line.Split(' ')); } } diff --git a/README.md b/README.md new file mode 100644 index 0000000..9012d92 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Пример для лекции про DI-контейнеры + + +Разные этапы внедрения DI-контейнера: + +* https://github.com/urfu-code/CommandLineTool/tree/ProceduralCode + +* https://github.com/urfu-code/CommandLineTool/tree/DIPCode + +* https://github.com/urfu-code/CommandLineTool/tree/ServiceLocatorCode + +* https://github.com/urfu-code/CommandLineTool/tree/DIContainerCode + +* https://github.com/urfu-code/CommandLineTool diff --git a/Writers/PromptConsoleWriter.cs b/Writers/PromptConsoleWriter.cs new file mode 100644 index 0000000..ada4a78 --- /dev/null +++ b/Writers/PromptConsoleWriter.cs @@ -0,0 +1,16 @@ +using System; +using System.IO; +using System.Text; + +namespace CommandLineTool +{ + public class PromptConsoleWriter : TextWriter + { + public override void WriteLine(string s) + { + Console.Out.WriteLine("> " + s); + } + + public override Encoding Encoding => Console.Out.Encoding; + } +} \ No newline at end of file diff --git a/Writers/RedTextConsoleWriter.cs b/Writers/RedTextConsoleWriter.cs new file mode 100644 index 0000000..304b9d1 --- /dev/null +++ b/Writers/RedTextConsoleWriter.cs @@ -0,0 +1,26 @@ +using System; +using System.IO; +using System.Text; + +namespace CommandLineTool +{ + public class RedTextConsoleWriter : TextWriter + { + public override void Write(char value) + { + var prev = Console.ForegroundColor; + + try + { + Console.ForegroundColor = ConsoleColor.Red; + Console.Out.Write(value); + } + finally + { + Console.ForegroundColor = prev; + } + } + + public override Encoding Encoding => Console.Out.Encoding; + } +} \ No newline at end of file AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル