2016-12-07 3 views
-1

私はこのトピックについていくつかの情報を見つけましたが、それはすべて典型的なクラスに関するものでした。私は下のクラスを汎用バージョンに変換する方法がわかりません。一般的に型付けされたHashSet

SqlHashSetクラスを使用してデータベースにパラメータの整数値を設定する既存のコードを継承しました。これは次のようになります。

namespace Services 
{ 
    public class SqlHashSet : HashSet<int>, IEnumerable<SqlDataRecord> 
    { 
     SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", SqlDbType.Int));  
     foreach (var data in this) 
     { 
      ret.SetValue(0, data); 
      yield return ret; 
     } 
    } 
} 

コードの構造上、SqlHashSetを使用する必要があります。私の問題は、の文字列のSqlHashSetが必要であるということです。

私はクラス宣言でHashSet<T>を使用することができるかもしれないと思っていますが、その後、私はまた、値の型がSqlDbType.intのですかSqlDbType.VarChar

だから、私の質問があるかどうかを確認する必要があります。

  1. これを行うことはできますか?

  2. <T>を使用するには何が必要ですか?

  3. 多分、3番目の質問はありません。多分私はそれがジェネリック型で動作し、値を設定するSqlDbTypeを決定する方法を理解したら、コードをステップ実行することができます。

+3

'これはできますか?' <=いいえ、ここに表示されているコードはコンパイルされません。結果を「収穫」する「foreach」ループは、メソッド本体の一部でなければならず、クラス本体内に単独で存在することはできません。 – Igor

+0

'を使うには何が必要なのですか?<=多分もっと良い質問は、変更に価値があるでしょうか?限られた数のプリミティブSQL型があり、SqlTypeは正確に1 .netプリミティブ型にアライメントする必要はありません。通常、リレーションシップはモデル構造によって異なります。例:.net DateTimeはDate、DateTime、またはDateTime2にマップできます。これはジェネリックを使用するのに最適な場所ではないかもしれません。 – Igor

+1

「HashSet」と「SqlDbType」の2つの一般的なパラメータがあります。あなたのクラスは 'SqlHashSet 'のようになります。あるいは、この 'SqlHashSet'を使用しないようにコードを書き直し、ライブラリの型に固執してください。 –

答えて

1

public abstract class SqlHashSetBase<T> : HashSet<T>, IEnumerable<SqlDataRecord> 
{ 
    protected abstract SqlDbType DbType { get; } 

    IEnumerator<SqlDataRecord> IEnumerable<SqlDataRecord>.GetEnumerator() 
    { 
     SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", this.DbType)); 
     foreach (T data in this) 
     { 
      ret.SetValue(0, data); 
      yield return ret; 
     } 
    } 
} 

その後、既存のクラスに変更します。

public class SqlHashSet : SqlHashSetBase<int> { 
    protected override SqlDbType DbType { 
     get { return SqlDbType.Int; } 
    } 
} 

を、新しいものを追加します。

public class SqlStringHashSet : SqlHashSetBase<string> { 
    protected override SqlDbType DbType { 
     get { return SqlDbType.NVarChar; } 
    } 
} 

あなたは抽出検討する必要がありますT => SqlDbTypeは独自のクラスにマッピングし、absを使用する代わりにパラメータとして渡しますトラクト法。 HashSet<T>から直接継承するのではなく、構図の使用を検討することもできます。

+0

SqlDbTypeとDbTypeで絡み合ったら、私はあなたの答えを使って終わりました。私はまだそれが正しく動作していない。 SQLサーバコードを完全に新しくしているので、このようなものは難しいです! – Patricia

+0

ちょっと、Lee:私はこれを働かせなければならない、またはそれをスクラップし、IDで行く必要があります。私は、誰かがSQL Serverデータベースに文字列のテーブルを送信しようとしている宇宙の歴史のどこかを知っています。私はこれがとても近いように感じる。実際には近すぎて今戻っていない。私はあなたのコード(単語のための単語)をコピーしましたが、実行はSqlHashSetBaseの無限ループに詰まらなくなりました。あなたができるなら、少し助け。 – Patricia

+1

@Patricia - 'HashSet 'から 'GetEnumerator()'を隠すために 'IEnumerable 'を明示的に実装する必要があると思います。次に、 'GetEnumerator'を再帰的に呼び出す代わりに、セット内のアイテムを繰り返し処理できます。更新を参照してください。 – Lee

1

;

あなたが本当に作成することはできません(あなたが投稿したコードがコンパイルされないことに注意してくださいあなたはクラスで直接文を書くことができない、彼らはこの方法でなければなりません) Tの種類に応じて別のSqlDbTypeを使用する必要があるためです。しかし、あなたが少し醜い何かを気にしないならば、あなたはこれを行うことができます:

public class SqlHashSet<T> : HashSet<T>, IEnumerable<SqlDataRecord> 
{ 
    private static readonly SqlDbType _sqlDbType = GetSqlDbType(); 
    private static SqlDbType GetSqlDbType() 
    { 
     if (typeof(T) == typeof(int)) 
      return SqlDbType.Int; 
     if (typeof(T) == typeof(string)) 
      return SqlDbType.String; 

     ... 

     throw new InvalidOperationException($"Can't find the SqlDbType for {typeof(T)}"); 
    } 

    ... 

    SqlDataRecord ret = new SqlDataRecord(new SqlMetaData("value", _sqlDbType)); 
} 

あなたが作成することの欠点を気にしない場合は李氏の答えで提案されているアプローチは、似ていますが、少しクリーナーです各値の型ごとに別々のクラス。あなたは、基本クラスを追加することができます

+0

ちょっと、SqlDbTypeとDbTypeに巻き込まれたら、私はLeeの答えを使って終わりました。私はまだそれが正常に動作していないが、私は彼にポイントを与える必要があるだろう。ご協力ありがとうございました。 – Patricia

関連する問題