2010-11-24 13 views
3

が好きな私はそれは非常に実用的見つけるので、私は 、他の人たちによって以前に行われた、ここでいくつかのコードをリファクタリングしようとしている、一般的な方法にここでは一例ですデザインの質問

protected void SetParameterValue(SqlParameter parameter, string parameterValue, bool isNullable) 
{ 
    if ((null == parameterValue || parameterValue == NULL_STRING) && isNullable) 
      parameter.Value = DBNull.Value; 
    else parameter.Value = parameterValue; 
} 

protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable) 
{ 
    if (parameterValue == NULL_INT && isNullable) 
      parameter.Value = DBNull.Value; 
    else parameter.Value = parameterValue; 
} 

protected void SetParameterValue(SqlParameter parameter, Int64 parameterValue, bool isNullable) 
{ 
    if (parameterValue == NULL_LONG && isNullable) 
      parameter.Value = DBNull.Value; 
    else parameter.Value = parameterValue; 
} 

のメソッドオーバーロードの多くを変換しますそれらは、もっとたくさんあります。今私は新しいタイプ(まだそれのための方法を持っていない)を受け入れるものを作成する必要があり、多分私は少しきれいにすることができる、これをより良くすることを決めた。 私の考えは、しかし、私は最善のアプローチだかわからない、私はこのジェネリックメソッドの内部で何をカプセル化することができますし、私も別の方法で何をすべきかが必要になります

protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue, bool isNullable) 

のようなものを作成することです。その価値はありますか?または "たくさんのメソッド"のアプローチは良いですか?私は一般的なものから何を得るでしょうか?ありがとう!

+0

極端な@Alex – msarchet

+0

Nullable型が利用できるようになったので、それらのNULL_INT、NULL_LONGなどの定数を削除し、代わりにデータ型として 'int?'、 'long?'を使用することをお勧めします。 – Heinzi

+0

NULL_INTなどの場所がたくさんあるという問題があります。たくさんのコードを変更しなくてもすばやくリファクタリングを行いたいのですが(多くの再テスト) –

答えて

3

スイッチの必要性を取り除く1つの方法は、ある種の辞書を使用して、可能なタイプごとにnullを構成する代理人を保持することです。私はあなたがこのためにオブジェクトに固執しなければならないと思うが。だから、辞書を持っているようにそれを設定したい:

private Dictionary<Type, Func<object, bool, bool>> _nullChecks = new Dictionary<Type, Func<object, bool, bool>>(); 

private void SetupNullChecks(){ 
    _nullChecks.Add(typeof(string), (object parameterValue, bool isNullable) => { return (null == parameterValue || parameterValue.ToString() == NULL_STRING) && isNullable; }); 
    _nullChecks.Add(typeof(int), (object parameterValue, bool isNullable) => { return (int)parameterValue == NULL_INT && isNullable; }); 
    _nullChecks.Add(typeof(long), (object parameterValue, bool isNullable) => { return (long)parameterValue == NULL_LONG && isNullable; }); 
} 

そして、あなたのチェックは次のようになります:Null許容型を使用するコードを変更、

public void SetParameterValue(SqlParameter parameter, object parameterValue, bool isNullable) 
{ 
    if (_nullChecks[parameterValue.GetType()].Invoke(parameterValue, isNullable)) 
     parameter.Value = DBNull.Value; 
    else parameter.Value = parameterValue; 
} 

他人によって示唆されているように、けれどもだろうより良くなる。

1

あなたは常に

Protected void SetParameterValue(SqlParameter parameter, 
object parameterValue, bool isNullable).... 

parameter.Valueは、各タイプの検証マイナスようにオブジェクトをとり行うことができ、あなたは本当にそれらを区切る必要はありません。

パラメータの型の型を反映し、型の型を取得し、その型に対してnull値が設定されているかどうかを確認する、検証型のパラメータメソッドを作成できます。

bool IsNull (object value){ 
    if (value is int){ 
    check int.. 
    } 
} 
//this is a quick and dirty example, there are more elegant ways to handle it. 

よう 何かがこれはあなたのタイプの検証と、すべてのオーバーロードを凝縮し、そしてそれはあまりにも一般的な方法の必要性を取り除きます。

+0

私は同じことを思っていた...私はおそらくnull_STRING、NULL_INTなどNullable または該当する場合nullに置き換えるしようとします。 –

+0

"オブジェクト"型を渡すのは良い習慣ではありませんし、ボクシング/アンボクシングがたくさんあります。同じことを達成できるジェネリックのものはありませんが、それぞれのタイプで巨大なswitch文を作成する必要はありませんか? –

+0

parameter.Valueがオブジェクトを取るので、まだ箱に行くでしょう。 – kemiller2002

0

bool isNullableではなくnullable型を使用できると思います。

protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue) 
{ 
if (parameterValue == null) 
    parameter.Value = DBNull.Value; 
else 
    parameter.Value = parameterValue; 
} 

おそらくこの署名でそれを呼び出すことができます。 同様 setParameterを(パラメータは、null) setParameterを(パラメータ、5)

+0

値の型をnullにすることはできません。 –

+0

もう一度待つと、SetParameter (param、null)が機能しません。 –

+0

はい、しかしSetParameter はそうなりません。値の型はnullにできないので、parameterValue == nullは常にfalseになります。 – kemiller2002

0

メソッド定義に「複数の署名」アプローチは完全に罰金です - それは私たちに多型を与えるものです。個人的には、リファクタリングではなく、そのテクニックを推奨したいと思います。しかし

、どのようなI だろう行うは、このようにパラメータをキャストし、「マスター」メソッドへの呼び出しを持つすべてのメソッド本体の繰り返しが、1つを置き換えるです:

protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable) 
{ 
    SetParameterValue(parameter, (Int64)parameterValue, isNullable); 
} 
protected void SetParameterValue(SqlParameter parameter, Int64 parameterValue, bool isNullable) 
{ 
    if (parameterValue == NULL_INT && isNullable) 
    parameter.Value = DBNull.Value; 
    else 
    parameter.Value = parameterValue; 
} 

これはことを前提としているparameterValueすることができますもちろん、あまりにも面倒なく再キャストすることができます。

0

最後に文章がある場合は、誰かがそれを行う必要があります。 オブジェクトまたはクラスに対してヌルであるものをオーバーライド/カプセル化するオプションがありますが、各コンセプトではnullをチェックする必要があります。

これは状況を改善するかどうかはわかりませんが、前述のようにメソッドを作成して最初に反復を分離したり、ヌルチェックのみを分離したりできます。最後は私が怒鳴るやったことです:

protected void SetParameterValue(SqlParameter parameter,object parameterValue){ 
    if(IsParameterNull(parameterValue) && parameter.IsNullable){ 
     parameter.Value = DBNull.Value; 
    } 
    else{ 
     parameter.Value = parameterValue; 
    } 
} 

List<NULLTYPE> nulls = new List<NULLTYPE>(){new NULLTYPE(NULL_INT), new NULLTYPE(NULL_LONG), new NULLTYPE(null)} 
protected bool IsParameterNull(object parameterValue){ 
    if(nulls.Contains(parameterValue)) return true; 
    else return false; 
} 

ここでの仕事は、値がリストに存在する場合はnull、それらのあなたの概念nulls.Contains(parameterValue)チェックをカプセル化するNULLTYPEクラスを作成することです。 さらに進んでContainsをオーバーライドして独自の方法で確認することもできますが、これにどれくらいの労力を費やしたいか考える必要があります。

+0

私が言うことを忘れてしまったもう一つのことは、あなたが本当に良いコードを作成したいのであれば、クリーンコードhttp://tinyurl.com/3xyq2obを読むことです。それは聖書ではなく、私は伝道者ではありませんが、それはあなたの心を開いたり、少しでも助けたりします。D –

+0

これは面白い解決策のようですが、NULLTYPEクラスの外観を理解できません。 ObjectをNULLTYPEと比較すると、List.Contains()はどのように動作しますか?キャスティングオペレータ?そして、(値以外の型)が実際にはnullであるかどうかをチェックするようなことを考慮する方法は?とにかくNULLTYPEのswitch文で終わることはありませんか? –

+0

不幸なことに、ある時点では、型の再構成とそのヌルまたはswitch文の意味のどちらかになります。それで、私はこれがあなたがそれにどれくらいの仕事をしたいのかという質問であると言ったのです。 NullTypeクラスは開発者の欲求に依存しますが、次のように簡単にできます。 –

関連する問題