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));
}
}








