我有一个包装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());
但是,我看到人们不喜欢流畅的界面,他们觉得自己变得过于健谈。
我还有其他选择吗?
我想要的,基本上:
我设想我的库的用户会通过添加新类和扩展方法来扩展它以获得intellisense支持,但是扩展方法不能在对象初始化器中使用,这意味着所有扩展看起来都像是事后的想法。那不是我想要的。
欢迎任何想法。
答案 0 :(得分: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" }
});
答案 1 :(得分:1)
我也不熟悉Mercurial,但有一种选择是抛出intellisense并使用匿名类型:
Repo.Execute(new
{
Message = "Your commit message",
AddRemove = true,
MyCommitExtension = null
});
您不能在属性名称中使用连字符,因此您需要从PascalCase替换为连字符小写。或者你可以用夸张的替换下划线。
我不确定我是否推荐这种方法,而不了解人们使用这些扩展的频率。在处理HTML属性时,这种方法在ASP.NET MVC框架中运行良好,但该方案的不同之处在于框架不需要处理值,它只是将它们直接写入输出。如果您根据以这种方式提供的值进行条件操作,或者您希望您的API对于那些不了解Mercurial命令行语法的人更容易被发现,那么您可以尝试其他方法。
答案 2 :(得分: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()}
};