0

我有一个包含 Mercurial 命令行客户端的类库。

我的目的是实现对所有内置命令的支持,但除此之外,还有大量的扩展。

所以我需要使我的库可扩展,因为我和其他人都可以添加对扩展的支持。我计划添加对一些更流行和典型的扩展的支持(至少有不少与 Mercurial 捆绑在一起的),但我仍然希望能够从外部扩展它。

目前,命令的语法如下所示:

Repo.Execute(new CommitCommand
{
    Message = "Your commit message",
    AddRemove = true,
});

然而,这并不适合扩展,程序员不会觉得扩展只是一部分。

例如,假设我公开了一个公共的附加命令行参数集合,我可以手动执行此操作:

var cmd = new CommitCommand
{
    Message = "Your commit message",
    AddRemove = true,
};
cmd.Arguments.Add("--my-commit-extension");
Repo.Execute(cmd);

对我来说似乎没有简单的方法来添加额外的扩展,使其可以设置为对象初始化程序的一部分。

我一直在考虑添加或切换到流畅的界面语法。在这种情况下,您可以编写如下内容:

Repo.Execute(new CommitCommand()
    .Message("Your commit message")
    .AddRemove()
    .MyCommitExtension());

但是,我看到人们不喜欢流畅的界面,他们觉得它们变得太健谈了。

我还有什么其他选择?

我想要的,基本上:

  • 一种常见的语法风格
    • 对于两个内置的东西
    • 以及我的图书馆用户添加的扩展

我设想我的库的用户将通过添加新类和扩展方法来扩展它以获得智能感知支持,但扩展方法不能用于对象初始化程序,这意味着所有扩展看起来都是事后才想到的。那不是我想要的。

欢迎任何想法。

4

3 回答 3

1

我不熟悉 Mercurial,您的问题似乎过于笼统,无法具体解决,但我可以解决一个特定的评论。

var cmd = new CommitCommand 
{ 
    Message = "Your commit message", 
    AddRemove = true, 
}; 
cmd.Arguments.Add("--my-commit-extension"); 
Repo.Execute(cmd); 

如果 CommitCommand.Arguments 是IList<T>你已经有能力使用初始化语法:

class CommitCommand
{
    public string Message { get; set; }
    public bool AddRemove { get; set; }
    public List<string> Arguments = new List<string>();
}

Repo.Execute(new CommitCommand
{
    Message = "Your commit message",
    AddRemove = true,
    Arguments = { "--my-commit-extension", "--my-other-commit-extension" }
});
于 2010-12-05T14:47:12.480 回答
1

我也不太熟悉 Mercurial,但一种选择是抛弃智能感知并使用匿名类型:

Repo.Execute(new 
{
    Message = "Your commit message",
    AddRemove = true,
    MyCommitExtension = null
});

您不能在属性名称中使用连字符,因此您需要将 PascalCase 替换为连字符小写。或者,您可以只用连字符替换下划线。

在不了解人们使用这些扩展的频率的情况下,我不确定是否会推荐这种方法。在处理 HTML 属性时,这种方法在 ASP.NET MVC 框架中运行良好,但该方案的不同之处在于框架不需要处理值,它只是将它们直接写入输出。如果您要根据以这种方式提供的值执行条件操作,或者您希望您的 API 更容易被那些不了解 Mercurial 命令行语法的人发现,那么您可以尝试另一种方法。

于 2010-12-05T15:02:32.277 回答
0

至于我流利的界面是好的。但是如果你想避免它,那么我可能会像这样使用 smth:

interface IExtension { ... }

class SomeExtension1 : IExtension { ... }
class SomeExtension2 : IExtension { ... }

class CommitCommand
{
    public string Message;
    public bool AddRemove;
    public readonly IList<IExtension> Extensions = new List<IExtension>();
}

它将允许以这种方式使用命令:

new CommitCommand
{
    Message = "",
    AddRemove = true,
    Extensions = {new SomeExtension1(), new SomeExtension2()}
};
于 2011-01-26T19:56:07.040 回答