2016-12-07 65 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. 也許沒有第三個問題;也許然後我可以通過代碼,一旦我有一個泛型類型的工作,並找出如何確定SqlDbType設置值。

+3

'我可以這樣做嗎?<=不,你在這裏顯示的代碼不會編譯,所以不會。產生結果的'foreach'循環必須是方法體的一部分,它不能獨立存在於類體中。 – Igor

+0

'我需要怎麼做才能使用?<=也許更好的問題是這個改變會值得嗎?原始SQL類型的數量有限,並且SqlType不必與1個.net原始類型進行對齊,通常這種關係取決於您的模型結構。例如:.net DateTime可以映射到Date,DateTime或DateTime2。這可能不是使用通用的最佳位置。 – Igor

+1

你可以採取簡單的方法,並有兩個通用參數,一個用於'HashSet'和一個用於'SqlDbType'。你的類看起來像'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

嘿,李:我必須得到這個工作或廢棄它,並與id一起去。我知道宇宙歷史中的某個地方,有人必須試圖向sql server db發送一個字符串表。我覺得這很接近。實際上現在離得太近了。我複製了你的代碼(單字逐句),但是執行被卡在SqlHashSetBase的無限循環中。有一點幫助,如果可以的話。 – Patricia

+1

@Patricia - 我想你必須顯式地實現'IEnumerable '來阻止它從'HashSet '中隱藏'GetEnumerator()'。然後,您可以迭代集合中的項目,而不是遞歸調用「GetEnumerator」。查看更新。 – Lee

1

(請注意,你已經發布的代碼無法編譯,你不能在一個類中直接寫語句,他們必須在方法)

您不能創建一個真正的通用類,因爲您需要使用不同的SqlDbType,具體取決於T的類型。但是,如果你不介意做一些稍微難看,你可以這樣做:

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