Gần đây tôi đã bắt gặp triển khai phân tích cú pháp dòng lệnh FubuCore Tôi thực sự thích nó, lý do là:
- nó rất dễ sử dụng - mặc dù tôi không thể tìm thấy tài liệu cho nó, giải pháp FubuCore cũng cung cấp một dự án chứa một bộ Bài kiểm tra đơn vị đẹp nói về chức năng hơn bất kỳ tài liệu nào có thể
- nó có một thiết kế hướng đối tượng đẹp, không lặp lại mã hoặc những thứ khác mà tôi từng có trong các ứng dụng phân tích cú pháp dòng lệnh của mình
- đó là khai báo: về cơ bản bạn viết các lớp cho các Lệnh và bộ tham số và trang trí chúng bằng các thuộc tính để đặt các tùy chọn khác nhau (ví dụ: tên, mô tả, bắt buộc / tùy chọn)
- thư viện thậm chí còn in một Biểu đồ sử dụng đẹp, dựa trên các định nghĩa này
Dưới đây là một ví dụ đơn giản về cách sử dụng này. Để minh họa cách sử dụng, tôi đã viết một tiện ích đơn giản có hai lệnh: - add (thêm một đối tượng vào danh sách - một đối tượng bao gồm tên (chuỗi), value (int) và cờ boolean) - list (danh sách tất cả các đối tượng hiện được thêm vào)
Trước hết, tôi đã viết một lớp Command cho lệnh 'add':
[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
public override bool Execute(CommandInput input)
{
State.Objects.Add(input); // add the new object to an in-memory collection
return true;
}
}
Lệnh này lấy một đối tượng CommandInput làm tham số, vì vậy tôi xác định tiếp theo:
public class CommandInput
{
[RequiredUsage("add"), Description("The name of the object to add")]
public string ObjectName { get; set; }
[ValidUsage("add")]
[Description("The value of the object to add")]
public int ObjectValue { get; set; }
[Description("Multiply the value by -1")]
[ValidUsage("add")]
[FlagAlias("nv")]
public bool NegateValueFlag { get; set; }
}
Lệnh tiếp theo là 'list', được thực hiện như sau:
[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
public override bool Execute(NullInput input)
{
State.Objects.ForEach(Console.WriteLine);
return false;
}
}
Lệnh 'list' không có tham số, vì vậy tôi đã định nghĩa một lớp NullInput cho việc này:
public class NullInput { }
Tất cả những gì còn lại bây giờ là kết nối điều này trong phương thức Main (), như thế này:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
Chương trình hoạt động như mong đợi, in gợi ý về cách sử dụng đúng trong trường hợp bất kỳ lệnh nào không hợp lệ:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
Và một cách sử dụng mẫu cho lệnh 'add':
Usages for 'add' (Add object)
add <objectname> [-nv]
-------------------------------------------------
Arguments
-------------------------------------------------
objectname -> The name of the object to add
objectvalue -> The value of the object to add
-------------------------------------------------
-------------------------------------
Flags
-------------------------------------
[-nv] -> Multiply the value by -1
-------------------------------------