一些 .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
上一篇
下一篇