我有一个流畅的界面问题。

我们有一些对象用作SQL接口的参数对象,这是一个例子:

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

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

以下是我添加了我要查看的内容的示例:

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

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

在上面的例子中,Substitute必须是SqlParameterOption类的静态属性(或者我只是添加一些括号的方法),而Precision必须是实例方法。

如果我对它们重新排序怎么办?

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

然后替换必须是实例属性而精确静态方法。这当然不会编译,我不能同时拥有静态和非静态属性或同名方法。

我该怎么做?我完全走错了吗?

在重读这个问题时,我有一个想法,下面这个不同的语法会更有意义吗?

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

在这种情况下,两者都是返回的实例方法,这将是SqlParameter选项的专用类或接口,如下所示。我不确定是否要转储 .With 部分,因为这会暴露对象的所有方法,而不仅仅是流利的

建议和一些好的网址将是最受欢迎的,我已经仔细研究了很多例子,但他们倾向于展示这样的例子:

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

(摘自此页


修改:在回复后进行跟进 来自 @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 所述,如果更改是不可逆转的,并且可能会发生逆转,建立状态并且失败有一点例外是我要去的方式。

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

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

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

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

我无法使用该语法,我将按照 @marxidad 的建议使用以下内容:

<*>

原因当然是将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());

Re:建立状态以便稍后应用而不是直接应用每次调用,如果在任何一种情况下都没有真正不可避免的副作用,那么这无关紧要,这取决于你的个人品味。如果选项与每个方法调用一起提交,并且您可能想要撤消该选项,那么您可能希望首先构建状态然后应用它。如果参数对象在您应用它们时对属性进行验证,那么最好使用直接应用程序,这样您就可以正确地获得验证反馈。

其他提示

您可以重载方法。例如,如果是Substitute()。您通常不能同时拥有方法的静态版本和实例版本,但扩展方法可能有一些用处...但如果两个版本的替换具有不同的含义,那么简单地返回不同的类型会更简洁,所以Substitute()的两个变体不能冲突。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top