0

我有一个包装Mercurial命令行客户端的类库。如何创建一个可扩展的API,并仍然使用对象初始值设定语法?

我的意图是实现对所有内置命令的支持,但除此之外,还有很多扩展。

所以我需要让我的库可扩展,因为其他人和我都可以添加对扩展的支持。我计划增加对一些比较流行和典型的扩展的支持(至少是与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()); 

但是,我看到人们不喜欢通顺接口,他们觉得他们变得过于健谈。

我还有其他选择吗?

我想要什么,基本上是:

  • 一个常见的语法风格
    • 对于这两个内置的我的媒体库的用户添加的东西
    • 除了扩展

我想我的图书馆的用户可以通过添加新的类和扩展方法来扩展它t intellisense支持,但扩展方法不能用于对象初始化器,这意味着所有的扩展看起来像是一些事后的想法。这不是我想要的。

欢迎任何想法。

回答

1

我对Mercurial并不熟悉,你的问题似乎过于笼统,无法专门解决,但我可以解决一个特别的问题。

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

如果CommitCommand。参数是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" } 
}); 
+0

是的,但不好意思,我的失误,我简化。我打算使用常规方法,以便使用库+扩展的程序员不必知道实际参数。 – 2010-12-05 18:21:48

1

我也是不那么熟悉的Mercurial,而是一种选择是智能感知出来扔掉,并使用匿名类型:

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

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

我不知道我会推荐这种方法不知道人们将使用这些扩展的频率。在处理HTML属性时,这种方法在ASP.NET MVC框架中效果很好,但是这种情况不同,因为框架不需要处理值,它只是直接将它们写入输出。如果您正在根据以这种方式提供的值采取条件操作,或者您希望您的API对于不知道Mercurial命令行语法的用户更容易发现,那么您可以尝试其他方法。

0

至于我流利的界面是好的。但是,如果你不想使用它,那么我可能会使用水木清华这样的:

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()} 
}; 
相关问题