我有一个流畅的界面问题.
我们有一些对象用作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 )
那么Substitute就必须是实例属性而Precision是静态方法.这当然不会编译,我不能同时拥有静态和非静态属性或方法.
我该怎么做呢?我在这里走错了路吗?
在重读这个问题时,我有一个想法,下面这个不同的语法会更有意义吗?
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 .Precision(15) .Substitute());
编辑: Gah,当我专注于一件事时,就是这样.
我不能使用那种语法,我会按照@marxidad的建议使用以下内容:
SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption() .Precision(15) .Substitute());
原因当然是将SqlParameter对象作为参数的方法无法处理With返回的对象,因此尽管构造并正确设置了SqlParameter对象,但它与预期用法不兼容.
SqlParameterOption's
方法都可以是返回同一对象的实例方法:
class SqlParameterOption { public SqlParameterOption Precision(int p) {/* ... */; return this;} public SqlParameterOption Substitute() {/* ... */; return this;} /* ... */ } /* ... */ SqlParameter.Int32(":ID", 1234).With(new SqlParameterOption() .Precision(15) .Substitute());
回复:建立国家要对直接与每个呼叫应用后应用,如果有在这两种情况下没有真正的irreverisible副作用,那么它并不重要,它取决于你的个人品味.如果选择上犯下与每个方法调用,并有你可能要撤消,那么你可能需要先建立状态,然后应用它一个机会.如果参数对象在您应用它们时对属性进行验证,那么最好使用直接应用程序,这样您就可以正确地获得验证反馈.