There's some interesting stuff quietly happening in the "Console App" world within open source .NET Core right now. Within the https://github.com/dotnet/command-line-api repository are three packages:

现在,开源.NET Core中的“控制台应用程序”世界中悄悄发生了一些有趣的事情。 在https://github.com/dotnet/command-line-api存储库中有三个软件包:

  • System.CommandLine.Experimental

    System.CommandLine.Experimental
  • System.CommandLine.DragonFruit

    System.CommandLine.DragonFruit
  • System.CommandLine.Rendering

    System.CommandLine.Rendering

These are interesting experiments and directions that are exploring how to make Console apps easier to write, more compelling, and more useful.

这些有趣的实验和方向正在探索如何使控制台应用程序更易于编写,更具吸引力和更有用。

The one I am the most infatuated with is DragonFruit.

我最着迷的是DragonFruit。

Historically Console apps in classic C look like this:

历史上,经典C语言中的控制台应用程序如下所示:

#include <stdio.h>

int main(int argc, char *argv[])
{
printf("Hello, World!\n");
return 0;
}

That first argument argc is the count of the number of arguments you've passed in, and argv is an array of pointers to 'strings,' essentially. The actual parsing of the command line arguments and the semantic meaning of the args you've decided on are totally on you.

第一个参数argc是您传入的参数数量的计数,而argv本质上是指向“字符串”的指针数组。 命令行参数的实际解析和您所决定的args的语义完全由您决定。

C# has done it this way, since always.

C#一直以来都是这样做的。

static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}

It's a pretty straight conceptual port from C to C#, right? It's an array of strings. Argc is gone because you can just args.Length.

这是从C到C#的非常简单的概念端口,对吗? 它是一个字符串数组。 Argc消失了,因为您只能args.Length。

If you want to make an app that does a bunch of different stuff, you've got a lot of string parsing before you get to DO the actual stuff you're app is supposed to do. In my experience, a simple console app with real proper command line arg validation can end up with half the code parsing crap and half doing stuff.

如果您想制作一个执行许多不同工作的应用程序,则必须先进行很多字符串解析,然后才能执行应做的实际工作。 以我的经验,一个具有真正正确的命令行arg验证的简单控制台应用程序最终可能需要一半的代码来分析废话,而另一半则可以完成工作。

myapp.com someCommand --param:value --verbose

The larger question - one that DragonFruit tries to answer - is why doesn't .NET do the boring stuff for you in an easy and idiomatic way?

更大的问题(DragonFruit试图回答的一个问题)是.NET为什么不以一种简单而惯用的方式为您提供无聊的工作?

From their docs, what if you could declare a strongly-typed Main method? This was the question that led to the creation of the experimental app model called "DragonFruit", which allows you to create an entry point with multiple parameters of various types and using default values, like this:

他们的文档中,如果可以声明一个强类型的Main方法怎么办? 这就是导致创建名为“ DragonFruit”的实验应用程序模型的问题,该模型允许您创建具有各种类型的多个参数并使用默认值的入口点,如下所示:

static void Main(int intOption = 42, bool boolOption = false, FileInfo fileOption = null)
{
    Console.WriteLine($"The value of intOption is: {intOption}");
    Console.WriteLine($"The value of boolOption is: {boolOption}");
    Console.WriteLine($"The value of fileOption is: {fileOption?.FullName ?? "null"}");
}

In this concept, the Main method - the entry point - is an interface that can be used to infer options and apply defaults.

在这个概念中,Main方法(入口点)是一个接口,可用于推断选项和应用默认值。

using System;

namespace DragonFruit
{
class Program
{
/// <summary>
/// DragonFruit simple example program
/// </summary>
/// <param name="verbose">Show verbose output</param>
/// <param name="flavor">Which flavor to use</param>
/// <param name="count">How many smoothies?</param>
static int Main(
bool verbose,
string flavor = "chocolate",
int count = 1)
{
if (verbose)
{
Console.WriteLine("Running in verbose mode");
}
Console.WriteLine($"Creating {count} banana {(count == 1 ? "smoothie" : "smoothies")} with {flavor}");
return 0;
}
}
}

I can run it like this:

我可以这样运行:

> dotnet run --flavor Vanilla --count 3   
Creating 3 banana smoothies with Vanilla

The way DragonFruit does this is super clever. During the build process, DragonFruit changes this public strongly typed Main to a private (so it's not seen from the outside - .NET won't consider it an entry point. It's then replaced with a Main like this, but you'll never see it as it's in the compiled/generated artifact.

DragonFruit做到这一点的方式非常聪明。 在构建过程中,DragonFruit将此强类型的公共Main更改为私有(因此从外部看不到-.NET不会将其视为入口点。然后将其替换为这样的Main,但您永远不会看到就像在已编译/生成的工件中一样。

public static async Task<int> Main(string[] args)
{
return await CommandLine.ExecuteAssemblyAsync(typeof(AutoGeneratedProgram).Assembly, args, "");
}

So DragonFruit has swapped your Main for its smarter Main and the magic happens! You'll even get free auto-generated help!

因此,DragonFruit将您的Main换成了更智能的Main,神奇的事情发生了! 您甚至可以获得免费的自动生成的帮助!

DragonFruit:
DragonFruit simple example program

Usage:
DragonFruit [options]

Options:
--verbose Show verbose output
--flavor <flavor> Which flavor to use
--count <count> How many smoothies?
--version Display version information

If you want less magic and more power, you can use the same APIs DragonFruit uses to make very sophisticated behaviors. Check out the Wiki and Repository for more and perhaps get involved in this open source project!

如果您想要更少的魔术和更多的功能,可以使用DragonFruit使用的相同API进行非常复杂的行为。 查看Wiki和存储库以获取更多信息,并可能参与这个开源项目!

I really like this idea and I'd love to see it taken further! Have you used DragonFruit on a project? Or are you using another command line argument parser?

我真的很喜欢这个主意,我希望看到它进一步发展! 您在项目上使用过DragonFruit吗? 还是使用另一个命令行参数解析器?

翻译自: https://www.hanselman.com/blog/dragonfruit-and-systemcommandline-is-a-new-way-to-think-about-net-console-apps

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐