dotnet-exec 小工具
Intro
在之前的文章中很多会有一些示例代码,这些代码一般都是一些很小的示例,尤其是介绍一些新特性的示例,基本上不会引用其他包,只有 SDK 就可以执行,对于这些示例,一般会每个实例单独一个文件,示例程序的入口文件是 MainTest
方法,都用 Main
会造成冲突,所以用了另外一个名字,而 Program
的 Main
方法里或者顶级程序语句中调用对应示例的 MainTest
,这样的话每当我想只执行每一个示例的时候我就需要修改 Program
中的方法调用
于是就想着写一个小工具,用来直接调用对应的示例,这样既不破坏原来 dotnet run
执行运行的效果,又可以直接执行某一个示例,今天开源的这个小工具 dotnet-exec
就是解决这个小问题的,下面来看一下如何使用以及如何实现的吧
GetStarted
首先需要安装 dotnet tool,dotnet tool 基于 .NET 6/7,需要安装 .NET 6 或者 .NET 7 SDK,SDK 安装之后
执行下面的命令即可安装
dotnet tool install -g dotnet-execute
对应的命令是 dotnet-exec
,可以使用 dotnet-exec -h
来看支持的选项
目前主要用到的 Options:
--entry
指定程序的入口,默认值是按我自己的习惯用的MainTest
,可以根据需要自定义,如果有Main
方法会优先使用Main
方法--lang-version
指定 C# 语言版本,默认使用Default
等同于Latest
,如果需要使用预览版特性需要指定为Preview
--args
/--arguments
指定用户需要传入的参数,等同于Main
方法的args
参数-c
/--configuration
指定编译的优化级别,默认是 Debug,不进行优化,可以指定为Release
Sample
百闻不如一见,来看几个使用的示例吧:
这里是 C# 10 中的一个常量插值字符串的示例,从下图中可以看到代码里没有定义 Main
方法,定义了一个 MainTest
的静态方法,我们执行 dotnet-exec .\ConstantInterpolatedStringSample.cs
可以看到,执行了 MainTest
方法中的逻辑并且,输出了期望的结果
这里是前段时间写的一个 C# 11 的一个新特性—— RawStringLiteral
我们可以通过 dotnet-exec .\RawStringLiteral.cs --lang-version Preview
来执行这个示例,这里我们指定了 --lang-version
为 Preview
以启用还在 Preview
的语言特性
针对原有的 Main
方法和顶级程序语句也是支持的,我们来看几个示例
Implement
它的实现原理其实比较简单,利用 Roslyn 去编译这个文件,增加了 Global using 的支持,并且会加上默认的 Global using,这样代码里可以简单一些,现在写的很多示例会启用隐式命名空间引用,这样会方便很多
首先会尝试编译为一个 Console 应用,顶级语句这种语法只支持 Console 应用,这样如果是顶级语句或者包含 Main 方法就和 dotnet run
的运行效果是一样的,如果没有 Main
方法,编译会报一个找不到 Main 方法的错误,然后会尝试编译为一个 dll 通过反射的方式调用自定义的入口,更多细节可以参考源码:https://github.com/WeihanLi/dotnet-exec/blob/1c83e366c81ab7a51e0995ed0f2a07845b668b89/src/dotnet-exec/CodeCompiler.cs#L38
More
目前只是做了比较简单处理,只编译了单个文件,而且没有检测项目中的包引用,如果有引用别的项目和文件,现在是不能处理的,后面可以解析文件所在的项目文件中的包引用依赖,编译整个项目,但是这样相对来说会复杂一些,实现起来可能不会走现在的方式了,后面有需求的话再说吧,暂时基本可以满足需要
如果你也有类似的需求,可以试一下看能否满足你的需要
References
https://github.com/WeihanLi/dotnet-exec
https://www.nuget.org/packages/dotnet-execute/