Skip to content

Commit f25dbb6

Browse files
committed
2 parents 961f60b + 5c966f1 commit f25dbb6

File tree

3 files changed

+161
-102
lines changed

3 files changed

+161
-102
lines changed

sandbox/SingleContainedApp/Program.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,36 @@ public async Task Timer([Option(0)]uint waitSeconds)
4848
}
4949
}
5050

51+
public class OverrideCheck : BatchBase
52+
{
53+
[Command("encode", "encode input string to base64url")]
54+
public void Encode([Option(0)]string input) => Console.WriteLine((input));
55+
56+
[Command("decode", "decode input base64url to string")]
57+
public void Decode([Option(0)]string input) => Console.WriteLine((input));
58+
59+
[Command("escape", "escape base64 to base64url")]
60+
public void Escape([Option(0)]string input) => Console.WriteLine((input));
61+
62+
[Command(new[] { "unescape", "-h" }, "unescape base64url to base64")]
63+
public void Unescape([Option(0)]string input) => Console.WriteLine((input));
64+
65+
[Command(new[] { "help", "-h", "-help", "--help" }, "show help")]
66+
public void Help()
67+
{
68+
Console.WriteLine("Usage: base64urls [-version] [-help] [decode|encode|escape|unescape] [args]");
69+
Console.WriteLine("E.g., run this: base64urls decode QyMgaXMgYXdlc29tZQ==");
70+
Console.WriteLine("E.g., run this: base64urls encode \"C# is awesome.\"");
71+
Console.WriteLine("E.g., run this: base64urls escape \"This+is/goingto+escape==\"");
72+
Console.WriteLine("E.g., run this: base64urls unescape \"This-is_goingto-escape\"");
73+
}
74+
}
75+
5176
class Program
5277
{
5378
static async Task Main(string[] args)
5479
{
55-
await new HostBuilder().RunBatchEngineAsync<MyFirstBatch>(args);
80+
await new HostBuilder().RunBatchEngineAsync<OverrideCheck>(args);
5681
}
5782
}
5883
}

src/MicroBatchFramework/BatchEngine.cs

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using Microsoft.Extensions.Logging;
2+
using System.Linq;
23
using System;
34
using System.Collections.Generic;
45
using System.Collections.ObjectModel;
56
using System.Reflection;
7+
using System.Text;
68
using System.Threading;
79
using System.Threading.Tasks;
810
using Utf8Json;
@@ -49,25 +51,41 @@ public async Task RunAsync(Type type, string[] args)
4951
}
5052

5153
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
54+
if (methods.Length == 0)
55+
{
56+
await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);
57+
return;
58+
}
59+
60+
MethodInfo helpMethod = null;
5261
foreach (var item in methods)
5362
{
5463
var command = item.GetCustomAttribute<CommandAttribute>();
5564
if (command != null)
5665
{
5766
if (args.Length > 0 && command.EqualsAny(args[0]))
5867
{
68+
// command's priority is first
5969
method = item;
6070
argsOffset = 1;
6171
goto RUN;
6272
}
73+
else
74+
{
75+
if (command.EqualsAny("help"))
76+
{
77+
helpMethod = item;
78+
}
79+
}
6380
}
6481
else
6582
{
6683
if (method != null)
6784
{
68-
goto FAIL;
85+
await SetFailAsync(ctx, "Found two public methods(wihtout command). Type:" + type.FullName + " Method:" + method.Name + " and " + item.Name);
86+
return;
6987
}
70-
method = item;
88+
method = item; // found single public(non-command) method.
7189
}
7290
}
7391

@@ -76,17 +94,25 @@ public async Task RunAsync(Type type, string[] args)
7694
goto RUN;
7795
}
7896

79-
FAIL:
80-
await SetFailAsync(ctx, "Method can not select. T of Run/UseBatchEngine<T> have to be contain single method or command. Type:" + type.FullName);
81-
return;
97+
// completely not found, invalid command name show help.
98+
if (helpMethod != null)
99+
{
100+
method = helpMethod;
101+
goto RUN;
102+
}
103+
else
104+
{
105+
Console.WriteLine(BatchEngine.BuildHelpParameter(methods));
106+
return;
107+
}
82108
}
83109
catch (Exception ex)
84110
{
85111
await SetFailAsync(ctx, "Fail to get method. Type:" + type.FullName, ex);
86112
return;
87113
}
88114

89-
RUN:
115+
RUN:
90116
await RunCore(ctx, type, method, args, argsOffset);
91117
}
92118

@@ -291,5 +317,92 @@ struct OptionParameter
291317
public string Value;
292318
public bool BooleanSwitch;
293319
}
320+
321+
internal static string BuildHelpParameter(MethodInfo[] methods)
322+
{
323+
var sb = new StringBuilder();
324+
foreach (var method in methods.OrderBy(x => x, new CustomSorter()))
325+
{
326+
var command = method.GetCustomAttribute<CommandAttribute>();
327+
if (command != null)
328+
{
329+
sb.AppendLine(string.Join(", ", command.CommandNames) + ": " + command.Description);
330+
}
331+
else
332+
{
333+
sb.AppendLine("argument list:");
334+
}
335+
336+
var parameters = method.GetParameters();
337+
if (parameters.Length == 0)
338+
{
339+
sb.AppendLine("()");
340+
}
341+
342+
foreach (var item in parameters)
343+
{
344+
// -i, -input | [default=foo]...
345+
346+
var option = item.GetCustomAttribute<OptionAttribute>();
347+
348+
if (option != null)
349+
{
350+
if (option.Index != -1)
351+
{
352+
sb.Append("[" + option.Index + "]");
353+
goto WRITE_DESCRIPTION;
354+
}
355+
else
356+
{
357+
sb.Append("-" + option.ShortName.Trim('-') + ", ");
358+
}
359+
}
360+
361+
sb.Append("-" + item.Name);
362+
363+
WRITE_DESCRIPTION:
364+
sb.Append(": ");
365+
366+
if (item.HasDefaultValue)
367+
{
368+
sb.Append("[default=" + (item.DefaultValue?.ToString() ?? "null") + "]");
369+
}
370+
371+
if (option != null && !string.IsNullOrEmpty(option.Description))
372+
{
373+
sb.Append(option.Description);
374+
}
375+
else
376+
{
377+
sb.Append(item.ParameterType.Name);
378+
}
379+
sb.AppendLine();
380+
}
381+
382+
sb.AppendLine();
383+
}
384+
385+
return sb.ToString();
386+
}
387+
388+
class CustomSorter : IComparer<MethodInfo>
389+
{
390+
public int Compare(MethodInfo x, MethodInfo y)
391+
{
392+
var xc = x.GetCustomAttribute<CommandAttribute>();
393+
var yc = y.GetCustomAttribute<CommandAttribute>();
394+
395+
if (xc != null)
396+
{
397+
return 1;
398+
}
399+
if (yc != null)
400+
{
401+
return -1;
402+
}
403+
404+
return x.Name.CompareTo(y.Name);
405+
}
406+
}
294407
}
295408
}

src/MicroBatchFramework/BatchEngineHostBuilderExtensions.cs

Lines changed: 16 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static IHostBuilder UseBatchEngine(this IHostBuilder hostBuilder, string[
3232
var (t, mi) = GetTypeFromAssemblies(args[1]);
3333
if (mi != null)
3434
{
35-
Console.WriteLine(BuildHelpParameter(new[] { mi }));
35+
Console.WriteLine(BatchEngine.BuildHelpParameter(new[] { mi }));
3636
}
3737
else
3838
{
@@ -101,13 +101,21 @@ public static IHostBuilder UseBatchEngine<T>(this IHostBuilder hostBuilder, stri
101101
{
102102
if (defaultMethod == null || (defaultMethod.GetParameters().Length != 0 && !defaultMethod.GetParameters().All(x => x.HasDefaultValue)))
103103
{
104-
Console.WriteLine(BuildHelpParameter(method));
105-
hostBuilder.ConfigureServices(services =>
104+
if (!hasHelp)
106105
{
107-
services.AddOptions<ConsoleLifetimeOptions>().Configure(x => x.SuppressStatusMessages = true);
108-
services.AddSingleton<IHostedService, EmptyHostedService>();
109-
});
110-
return hostBuilder;
106+
Console.WriteLine(BatchEngine.BuildHelpParameter(method));
107+
hostBuilder.ConfigureServices(services =>
108+
{
109+
services.AddOptions<ConsoleLifetimeOptions>().Configure(x => x.SuppressStatusMessages = true);
110+
services.AddSingleton<IHostedService, EmptyHostedService>();
111+
});
112+
return hostBuilder;
113+
}
114+
else
115+
{
116+
// override default Help
117+
args = new string[] { "help" };
118+
}
111119
}
112120
}
113121

@@ -124,7 +132,7 @@ public static IHostBuilder UseBatchEngine<T>(this IHostBuilder hostBuilder, stri
124132

125133
if (!hasHelp && args.Length == 1 && args[0].Equals(HelpCommand, StringComparison.OrdinalIgnoreCase))
126134
{
127-
Console.WriteLine(BuildHelpParameter(method));
135+
Console.WriteLine(BatchEngine.BuildHelpParameter(method));
128136
hostBuilder.ConfigureServices(services =>
129137
{
130138
services.AddOptions<ConsoleLifetimeOptions>().Configure(x => x.SuppressStatusMessages = true);
@@ -170,73 +178,6 @@ static void ShowMethodList()
170178
}
171179
}
172180

173-
static string BuildHelpParameter(MethodInfo[] methods)
174-
{
175-
var sb = new StringBuilder();
176-
foreach (var method in methods.OrderBy(x => x, new CustomSorter()))
177-
{
178-
var command = method.GetCustomAttribute<CommandAttribute>();
179-
if (command != null)
180-
{
181-
sb.AppendLine(string.Join(", ", command.CommandNames) + ": " + command.Description);
182-
}
183-
else
184-
{
185-
sb.AppendLine("argument list:");
186-
}
187-
188-
var parameters = method.GetParameters();
189-
if (parameters.Length == 0)
190-
{
191-
sb.AppendLine("()");
192-
}
193-
194-
foreach (var item in parameters)
195-
{
196-
// -i, -input | [default=foo]...
197-
198-
var option = item.GetCustomAttribute<OptionAttribute>();
199-
200-
if (option != null)
201-
{
202-
if (option.Index != -1)
203-
{
204-
sb.Append("[" + option.Index + "]");
205-
goto WRITE_DESCRIPTION;
206-
}
207-
else
208-
{
209-
sb.Append("-" + option.ShortName.Trim('-') + ", ");
210-
}
211-
}
212-
213-
sb.Append("-" + item.Name);
214-
215-
WRITE_DESCRIPTION:
216-
sb.Append(": ");
217-
218-
if (item.HasDefaultValue)
219-
{
220-
sb.Append("[default=" + (item.DefaultValue?.ToString() ?? "null") + "]");
221-
}
222-
223-
if (option != null && !string.IsNullOrEmpty(option.Description))
224-
{
225-
sb.Append(option.Description);
226-
}
227-
else
228-
{
229-
sb.Append(item.ParameterType.Name);
230-
}
231-
sb.AppendLine();
232-
}
233-
234-
sb.AppendLine();
235-
}
236-
237-
return sb.ToString();
238-
}
239-
240181
static List<Type> GetBatchTypes()
241182
{
242183
List<Type> batchBaseTypes = new List<Type>();
@@ -307,25 +248,5 @@ static List<Type> GetBatchTypes()
307248

308249
return (null, null);
309250
}
310-
311-
class CustomSorter : IComparer<MethodInfo>
312-
{
313-
public int Compare(MethodInfo x, MethodInfo y)
314-
{
315-
var xc = x.GetCustomAttribute<CommandAttribute>();
316-
var yc = y.GetCustomAttribute<CommandAttribute>();
317-
318-
if (xc != null)
319-
{
320-
return 1;
321-
}
322-
if (yc != null)
323-
{
324-
return -1;
325-
}
326-
327-
return x.Name.CompareTo(y.Name);
328-
}
329-
}
330251
}
331252
}

0 commit comments

Comments
 (0)