您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何使用.Net Core編寫命令行工具,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
命令行工具(CLI)
命令行工具(CLI)是在圖形用戶界面得到普及之前使用最為廣泛的用戶界面,它通常不支持鼠標,用戶通過鍵盤輸入指令,計算機接收到指令后,予以執行。
通常認為,命令行工具(CLI)沒有圖形用戶界面(GUI)那么方便用戶操作。因為,命令行工具的軟件通常需要用戶記憶操作的命令,但是,由于其本身的特點,命令行工具要較圖形用戶界面節約計算機系統的資源。在熟記命令的前提下,使用命令行工具往往要較使用圖形用戶界面的操作速度要快。所以,圖形用戶界面的操作系統中,都保留著可選的命令行工具。
另外,命令行工具(CLI)應該是一個開箱即用的工具,不需要安裝任何依賴。
一些熟悉的CLI工具如下:
1. dotnet cli
2. vue cli
3.angular cli
4. aws cli
5.azure cli
指令設計
本文將使用.Net Core(版本3.1.102)編寫一個CLI工具,實現配置管理以及條目(item)管理(調用WebApi實現),詳情如下:
框架說明
編寫CLI使用的主要框架是CommandLineUtils,它主要有以下優勢:
1. 良好的語法設計
2. 支持依賴注入
3. 支持generic host
WebApi
提供api讓cli調用,實現條目(item)的增刪改查:
[Route("api/items")] [ApiController] public class ItemsController : ControllerBase { private readonly IMemoryCache _cache; private readonly string _key = "items"; public ItemsController(IMemoryCache memoryCache) { _cache = memoryCache; } [HttpGet] public IActionResult List() { var items = _cache.Get<List<Item>>(_key); return Ok(items); } [HttpGet("{id}")] public IActionResult Get(string id) { var item = _cache.Get<List<Item>>(_key).FirstOrDefault(n => n.Id == id); return Ok(item); } [HttpPost] public IActionResult Create(ItemForm form) { var items = _cache.Get<List<Item>>(_key) ?? new List<Item>(); var item = new Item { Id = Guid.NewGuid().ToString("N"), Name = form.Name, Age = form.Age }; items.Add(item); _cache.Set(_key, items); return Ok(item); } [HttpDelete("{id}")] public IActionResult Delete(string id) { var items = _cache.Get<List<Item>>(_key); var item = items?.SingleOrDefault(n => n.Id == id); if (item == null) { return NotFound(); } items.Remove(item); _cache.Set(_key, items); return Ok(); } }
CLI
1. Program - 函數入口
[HelpOption(Inherited = true)] //顯示指令幫助,并且讓子指令也繼承此設置 [Command(Description = "A tool to communicate with web api"), //指令描述 Subcommand(typeof(ConfigCommand), typeof(ItemCommand))] //子指令 class Program { public static int Main(string[] args) { //配置依賴注入 var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(PhysicalConsole.Singleton); serviceCollection.AddSingleton<IConfigService, ConfigService>(); serviceCollection.AddHttpClient<IItemClient, ItemClient>(); var services = serviceCollection.BuildServiceProvider(); var app = new CommandLineApplication<Program>(); app.Conventions .UseDefaultConventions() .UseConstructorInjection(services); var console = (IConsole)services.GetService(typeof(IConsole)); try { return app.Execute(args); } catch (UnrecognizedCommandParsingException ex) //處理未定義指令 { console.WriteLine(ex.Message); return -1; } } //指令邏輯 private int OnExecute(CommandLineApplication app, IConsole console) { console.WriteLine("Please specify a command."); app.ShowHelp(); return 1; } }
2. ConfigCommand和ItemCommand - 實現的功能比較簡單,主要是指令描述以及指定對應的子指令
[Command("config", Description = "Manage config"), Subcommand(typeof(GetCommand), typeof(SetCommand))] public class ConfigCommand { private int OnExecute(CommandLineApplication app, IConsole console) { console.Error.WriteLine("Please submit a sub command."); app.ShowHelp(); return 1; } } [Command("item", Description = "Manage item"), Subcommand(typeof(CreateCommand), typeof(GetCommand), typeof(ListCommand), typeof(DeleteCommand))] public class ItemCommand { private int OnExecute(CommandLineApplication app, IConsole console) { console.Error.WriteLine("Please submit a sub command."); app.ShowHelp(); return 1; } }
3.ConfigService - 配置管理的具體實現,主要是文件讀寫
public interface IConfigService { void Set(); Config Get(); } public class ConfigService: IConfigService { private readonly IConsole _console; private readonly string _directoryName; private readonly string _fileName; public ConfigService(IConsole console) { _console = console; _directoryName = ".api-cli"; _fileName = "config.json"; } public void Set() { var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _directoryName); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var config = new Config { //彈出交互框,讓用戶輸入,設置默認值為http://localhost:5000/ Endpoint = Prompt.GetString("Specify the endpoint:", "http://localhost:5000/") }; if (!config.Endpoint.EndsWith("/")) { config.Endpoint += "/"; } var filePath = Path.Combine(directory, _fileName); using (var outputFile = new StreamWriter(filePath, false, Encoding.UTF8)) { outputFile.WriteLine(JsonConvert.SerializeObject(config, Formatting.Indented)); } _console.WriteLine($"Config saved in {filePath}."); } public Config Get() { var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _directoryName, _fileName); if (File.Exists(filePath)) { var content = File.ReadAllText(filePath); try { var config = JsonConvert.DeserializeObject<Config>(content); return config; } catch { _console.WriteLine("The config is invalid, please use 'config set' command to reset one."); } } else { _console.WriteLine("Config is not existed, please use 'config set' command to set one."); } return null; } }
4.ItemClient - 調用Web Api的具體實現,使用HttpClientFactory的方式
public interface IItemClient { Task<string> Create(ItemForm form); Task<string> Get(string id); Task<string> List(); Task<string> Delete(string id); } public class ItemClient : IItemClient { public HttpClient Client { get; } public ItemClient(HttpClient client, IConfigService configService) { var config = configService.Get(); if (config == null) { return; } client.BaseAddress = new Uri(config.Endpoint); Client = client; } public async Task<string> Create(ItemForm form) { var content = new StringContent(JsonConvert.SerializeObject(form), Encoding.UTF8, "application/json"); var result = await Client.PostAsync("/api/items", content); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var item = Deserialize<Item>(stream); return $"Item created, info:{item}"; } return "Error occur, please again later."; } public async Task<string> Get(string id) { var result = await Client.GetAsync($"/api/items/{id}"); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var item = Deserialize<Item>(stream); var response = new StringBuilder(); response.AppendLine($"{"Id".PadRight(40, ' ')}{"Name".PadRight(20, ' ')}Age"); response.AppendLine($"{item.Id.PadRight(40, ' ')}{item.Name.PadRight(20, ' ')}{item.Age}"); return response.ToString(); } return "Error occur, please again later."; } public async Task<string> List() { var result = await Client.GetAsync($"/api/items"); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var items = Deserialize<List<Item>>(stream); var response = new StringBuilder(); response.AppendLine($"{"Id".PadRight(40, ' ')}{"Name".PadRight(20, ' ')}Age"); if (items != null && items.Count > 0) { foreach (var item in items) { response.AppendLine($"{item.Id.PadRight(40, ' ')}{item.Name.PadRight(20, ' ')}{item.Age}"); } } return response.ToString(); } return "Error occur, please again later."; } public async Task<string> Delete(string id) { var result = await Client.DeleteAsync($"/api/items/{id}"); if (result.IsSuccessStatusCode) { return $"Item {id} deleted."; } if (result.StatusCode == HttpStatusCode.NotFound) { return $"Item {id} not found."; } return "Error occur, please again later."; } private static T Deserialize<T>(Stream stream) { using var reader = new JsonTextReader(new StreamReader(stream)); var serializer = new JsonSerializer(); return (T)serializer.Deserialize(reader, typeof(T)); } }
如何發布
在項目文件中設置發布程序的名稱(AssemblyName):
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <AssemblyName>api-cli</AssemblyName> </PropertyGroup>
進入控制臺程序目錄:
cd src/NetCoreCLI
發布Linux使用版本:
dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true
發布Windows使用版本:
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true
發布MAC使用版本:
dotnet publish -c Release -r osx-x64 /p:PublishSingleFile=true
使用示例
這里使用Linux作為示例環境。
1. 以docker的方式啟動web api
2. 虛擬機上沒有安裝.net core的環境
3. 把編譯好的CLI工具拷貝到虛擬機上,授權并移動到PATH中(如果不移動,可以通過./api-cli的方式調用)
sudo chmod +x api-cli #授權 sudo mv ./api-cli /usr/local/bin/api-cli #移動到PATH
4. 設置配置文件:api-cli config set
5. 查看配置文件:api-cli config get
6. 創建條目:api-cli item create
7. 條目列表:api-cli item list
8. 獲取條目:api-cli item get
9. 刪除條目:api-cli item delete
10. 指令幫助:api-cli -h, api-cli config -h, api-cli item -h
11. 錯誤指令:api-cli xxx
關于“如何使用.Net Core編寫命令行工具”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。