日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

使用.Net Core编写命令行工具(CLI)

發布時間:2023/12/4 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用.Net Core编写命令行工具(CLI) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用.Net Core編寫命令行工具(CLI)

命令行工具(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

  • 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

      


    源碼地址

      https://github.com/ErikXu/NetCoreCLI


    參考資料

    https://docs.microsoft.com/en-us/dotnet/core/rid-catalog#using-rids](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog#using-rids

    https://medium.com/swlh/build-a-command-line-interface-cli-program-with-net-core-428c4c85221

    關注架構師高級俱樂部

    開啟架構之路

    總結

    以上是生活随笔為你收集整理的使用.Net Core编写命令行工具(CLI)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。