c# - C# 中的流畅接口(interface)

标签 c# fluent-interface

我对流畅的界面有疑问。

我们有一些对象用作 SQL 接口(interface)的参数对象,下面是一个示例:

using (DatabaseCommand cmd = conn.CreateCommand(
    "SELECT A, B, C FROM tablename WHERE ID = :ID",
    SqlParameter.Int32(":ID", 1234)))
{
    ...
}

对于其中一些参数,我想启用一些专门的选项,但我没有向 Int32 方法(这只是众多方法之一)添加更多属性,我想我会研究流畅的接口(interface)。

这是一个示例,其中我添加了我正在研究的内容:

SqlParameter.Int32(":ID", 1234).With(SqlParameterOption
    .Substitute
    .Precision(15)
)

我知道这两个选项对这种类型的参数没有意义,但这不是问题所在。

在上述情况下,Substitute 必须是 SqlParameterOption 类上的静态属性(或者方法,如果我只是添加一些括号),而 Precision 必须是实例方法。

如果我重新订购它们会怎样?

SqlParameter.Int32(":ID", 1234).With(SqlParameterOption
    .Precision(15)
    .Substitute
)

那么 Substitute 必须是实例属性,Precision 必须是静态方法。这当然不会编译,我不能同时拥有同名的静态和非静态属性或方法。

我该怎么做?我在这里完全走错路了吗?

在重读问题时,我想到了,下面这种不同的语法是否更有意义?

SqlParameter.Int32(":ID", 1234).With
    .Precision(15)
    .Substitute

在这种情况下,两者都将是任何 With 返回的实例方法,这将是像这样的 SqlParameter 选项的专用类或接口(interface)。我不确定是否要放弃 .With 部分,因为这会公开对象的所有方法,而不仅仅是 fluent 方法。

建议和一些好的 url 是最受欢迎的,我搜索了很多例子,但他们倾向于显示这样的例子:

order
    .AddFreeShipping()
    .IncludeItem(15)
        .SuppressTax();

(从 this page 中提取)


编辑:回应后跟进 来自 @marxidad :

class SqlParameterOption
{
    public SqlParameterOption Precision(int p) {/* ... */; return this;}
    public SqlParameterOption Substitute() {/* ... */; return this;}
    /* ... */       
}

/* ... */
SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

使用这种方法,With 必须获取对象,并将其应用于参数。我没意见。

如果我使用我添加的语法作为例子,它会是这样的:

SqlParameter.Int32(":ID", 1234).With
                               .Precision(15)
                               .Substitute());

在这种情况下,With 不知道链何时结束,因此每个选项都必须直接应用其效果。

什么是首选?这些选项构建了一个稍后必须应用的效果对象,还是每个效果都直接应用它的效果?

我的决定: 作为@marxidad说,如果更改是不可逆的,并且可能会发生逆转,则建立状态并在某个时候失败,但有一个异常(exception)是我要走的路。

但是,在这种情况下,我将采用一种更简单的方法,即直接修改 SqlParameter 对象。

在这种情况下,我的代码将如下所示:

SqlParameter.Int32(":ID", 1234).With
                               .Precision(15)
                               .Substitute());

编辑:啊,当我只专注于一件事时就是这样。

我不能使用那个语法,我将按照 @marxidad 的建议使用以下语法:

SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

当然是因为以SqlParameter 对象为参数的方法无法处理With 返回的对象,所以虽然SqlParameter 对象构造和设置正确,但它变得与预期用途不兼容。

最佳答案

SqlParameterOption 的 方法都可以是返回相同对象的实例方法:

class SqlParameterOption
 {
    public SqlParameterOption Precision(int p) {/* ... */; return this;}
    public SqlParameterOption Substitute() {/* ... */; return this;}
    /* ... */       
 }

/* ... */
SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption()
                                           .Precision(15)
                                           .Substitute());

回复:建立稍后应用的状态与每次调用时直接应用,如果在任何一种情况下都没有真正不可逆转的副作用,那么这并不重要,这取决于您个人品味。如果每个方法调用都提交了选项,并且您可能想撤消它,那么您可能想先建立状态,然后再应用它。如果参数对象在您应用它们时为您进行属性之间的验证,那么最好直接应用,这样您将以正确的方式获得验证反馈。

关于c# - C# 中的流畅接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/218024/

相关文章:

c# - 温莎城堡 : Auto-register types from one assembly that implement interfaces from another

delphi - Delphi 中具有继承性的流畅界面

c# - 如何在 NUnit 中编写需要括号的流畅约束

c# - 如何使用 CaSTLe Windsor - Fluent Interface 来注册通用接口(interface)?

apache-flex - 处理异步控制结构(Fluent Interface?)

c# - 在 IModule 中注册类型和封装问题

c# - 如何从数组创建不同值的字符串(包括其他字符)

javascript - 如何禁用 asp 按钮上的回发并仍然运行 OnClick 方法?

c# - 在 ASP.NET MVC 中创建数据库回调的最有效方法

c# - Saxon XSLT 传递参数