22// Imports
33// ---------------------------------------------------------------------------------------------------------------------
44using Microsoft . Extensions . DependencyInjection ;
5+ using Microsoft . Extensions . Logging ;
6+ using System . Diagnostics . CodeAnalysis ;
57using System . Text . RegularExpressions ;
68
79namespace CodeOfChaos . CliArgsParser ;
@@ -11,17 +13,19 @@ namespace CodeOfChaos.CliArgsParser;
1113public partial class CliParser : ICliParser {
1214 public required Lazy < IServiceProvider > ? ServiceProvider { get ; init ; }
1315 public required ICommandProvider CommandProvider { get ; init ; }
14-
15- [ GeneratedRegex ( @"\s+" ) ] private static partial Regex FindEmptySpacesRegex { get ; }
1616
17+ private ILogger < CliParser > ? Logger => ServiceProvider ? . Value . GetService < ILogger < CliParser > > ( ) ;
18+
19+ [ GeneratedRegex ( @"\s+" ) ] private static partial Regex FindEmptySpacesRegex { get ; }
20+
1721 // -----------------------------------------------------------------------------------------------------------------
1822 // Methods
1923 // -----------------------------------------------------------------------------------------------------------------
20- internal CliParser ( ) { }
24+ internal CliParser ( ) { }
2125 public static CliParserBuilder CreateBuilder ( ) {
2226 return new CliParserBuilder ( ) ;
2327 }
24-
28+
2529 public ValueTask ExecuteAsync ( string [ ] args , CancellationToken ct = default ) => ExecuteAsync ( ArgsInputHelper . ToOneLine ( args ) , ct ) ;
2630 public async ValueTask ExecuteAsync ( string input , CancellationToken ct = default ) {
2731 input = input . Replace ( "\\ \" " , "\" " ) ;
@@ -32,21 +36,47 @@ public async ValueTask ExecuteAsync(string input, CancellationToken ct = default
3236 await Task . WhenAll ( tasks ) ;
3337 return ;
3438 }
35-
39+
3640 string [ ] tokens = FindEmptySpacesRegex . Split ( input ) ;
3741 string commandName = tokens [ 0 ] ;
3842 string parameterInput = string . Join ( " " , tokens . Skip ( 1 ) ) ;
3943
40- if ( ! CommandProvider . TryGetCommand ( commandName , out Type ? commandType ) ) throw new Exception ( "no Command found" ) ;
41-
42- ICliCommand ? command = ServiceProvider is not null
43- ? ( ICliCommand ? ) ActivatorUtilities . CreateInstance ( ServiceProvider . Value , commandType )
44- : Activator . CreateInstance ( commandType ) as ICliCommand ;
44+ if ( ! CommandProvider . TryGetCommand ( commandName , out Type ? commandType ) ) {
45+ if ( Logger is null ) throw new Exception ( $ "Could not find command by name { commandName } ") ;
46+ Logger . LogWarning ( "Could not find command by name {name}" , commandName ) ;
47+ return ;
48+ }
49+
50+ if ( ! TryCreateCommandInstance ( commandType , out ICliCommand ? command ) ) {
51+ if ( Logger is null ) throw new Exception ( $ "Could not instantiate command with type { commandType . FullName } ") ;
52+ Logger . LogWarning ( "Could not instantiate command with type {type}" , commandType . FullName ) ;
53+ return ;
54+
55+ }
4556
46-
47- if ( command is null ) throw new Exception ( "no Command found" ) ;
48-
4957 ParameterDictionary parameterDictionary = ParameterDictionary . FromString ( parameterInput ) ;
5058 await command . StartExecution ( parameterDictionary , ct ) ;
5159 }
60+
61+ private bool TryCreateCommandInstance ( Type commandType , [ NotNullWhen ( true ) ] out ICliCommand ? command ) {
62+ try {
63+ if ( ServiceProvider is null ) {
64+ object ? directInstance = Activator . CreateInstance ( commandType ) ;
65+ command = directInstance as ICliCommand ;
66+ return command is not null ;
67+ }
68+
69+ IServiceScope scope = ServiceProvider . Value . CreateScope ( ) ;
70+ object diInstance = ActivatorUtilities . CreateInstance ( scope . ServiceProvider , commandType ) ;
71+ command = diInstance as ICliCommand ;
72+ return command is not null ;
73+ }
74+ catch ( Exception e ) {
75+ // Throw if we cant log
76+ if ( Logger is null ) throw ;
77+ Logger . LogWarning ( e , "Failed to create command instance" ) ;
78+ command = null ;
79+ return false ;
80+ }
81+ }
5282}
0 commit comments