一些 .NET 新建项目模板库

ConsoleAppFramework

https://github.com/Cysharp/ConsoleAppFramework

# 这里使用了注入与 zlogger
var app = ConsoleApp.Create()
.ConfigureServices(it => it.AddSingleton<DownloadCommander>())
.ConfigureLogging(it =>
{
配置 zlogger
it.ClearProviders();
it.SetMinimumLevel(LogLevel.Trace);
it.AddZLoggerConsole(options => options.SetLogFormat());
// it.AddZLoggerFile("log.txt");
it.AddZLoggerRollingFile(options =>
{
options.FilePathSelector = (dt, index) => $"logs/{dt:yyyy-MM-dd}_{index}.log";
options.RollingInterval = RollingInterval.Day;
options.RollingSizeKB = 1024 * 1024;
options.SetLogFormat();
});
});
;
# 主命令
app.Add("", async ([FromServices] DownloadCommander commander, CancellationToken cancellationToken) => { await commander.RunAsync(cancellationToken); });
# 这里可以放一些临时合集
app.Add("Add", (int x, int y) => Console.WriteLine(x + y));
app.Add("Multiply", (double x, double y) => { Console.WriteLine(x * y); });
app.Add("Delay", async () => { await Task.Delay(TimeSpan.FromSeconds(5)); });
app.Run(args);

格式化日志输出

// 格式化 zlog 输出格式
public static class ZlogMessageFormattingTool
{
private static readonly ConcurrentDictionary<string, string> SrotNameDict = new();
public static void SetLogFormat(this ZLoggerOptions options, bool shortName = false)
{
options.UsePlainTextFormatter(formatter =>
{
formatter.SetPrefixFormatter($"{0} [{1:short}] [{2}] ",
(in MessageTemplate template, in LogInfo info) => template.Format(info.Timestamp, info.LogLevel, GetCategoryName(info.Category, shortName)));
});
}
private static object GetCategoryName(LogCategory category, bool? shortName)
{
return shortName.GetValueOrDefault() ? category.Name : SrotNameDict.GetOrAdd(category.Name, name => name.Split('.').Last());
}
}

直接运行

如果不用注入这一套,直接运行的话,如下

ConsoleApp.Run(args, (int foo, int bar) => Console.WriteLine($"Sum: {foo + bar}"));
await ConsoleApp.RunAsync(args, async Task<int> (int foo, int bar, CancellationToken token) => { return 1;});

显示注释及参数

如果要将注释显示到命令的 --help 中。需要写一个类,在类函数中进行注释
[Command("")] 中设置为默认命令
简写参数名在注释中使用 -x, 注明,多个使用 | 分隔
[Argument] 顺序参数,不需要参数名
参数是数组的话,传入如下格式 [xx, xx, xx, ]
string optional = "abcde" 为指定参数,可忽略参数
bool 作为标志位解析,传入参数名为 true
enum 不区分大小写解析
一般参数使用 IParsable.TryParse 解析
如果是对象,自动使用 JsonSerializer.Deserialize<T> 解析
使用 params string[] paramsArray 接收不定长参数

// 这个类中的 publice 方法自动变为命令,而且注释自动生成到 --help 中
app.Add<CommandHelper>();
app.Run(args);
// 为了在命令中显示注释,使用类进行加载
public class CommandHelper
{
/// <summary>
/// 为了显示注释,这是加法
/// </summary>
/// <param name="a">加数 1</param>
/// <param name="b">加数 2</param>
/// <returns></returns>
public async Task<int> RunAddAsync([Argument] int a, [Argument] int b, [FromServices] ILogger<CommandHelper> logger)
{
var result = a + b;
// zlogger 方式写入日志, 会有效率优化
logger.ZLogInformation($"result: {result}");
return 0;
}
/// <summary>
/// 测试命令
/// </summary>
/// <param name="count">-c, 简写参数名 -c, 多个使用 | 分隔</param>
/// <param name="commander"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[Command("")] // 默认命令
public async Task<int> RunAsync(int count, [FromServices] DownloadCommander commander, CancellationToken cancellationToken)
{
return await commander.RunAsync(count, cancellationToken);
}
}

其它

https://github.com/Tyrrrz/CliFx
https://github.com/spectreconsole/spectre.console
https://github.com/jasontaylordev/CleanArchitecture
https://github.com/mayuki/Cocona
> Cocona
> Cocona.lite
https://github.com/devlead/Devlead.Console.Template
> 项目说明:https://www.devlead.se/posts/2021/2021-01-15-my-preferred-console-stack
> 对 rider 相当不友好
https://github.com/nuitsjp/Wpf.Extensions.Hosting
https://github.com/Keboo/DotnetTemplates
上一篇
下一篇