2012-08-16 71 views
14

有沒有更好的方法來寫這個?作爲一個類也許,而不是兩個。可選的泛型類型

using System; 

namespace SnippetTool.Repositories 
{ 
    public abstract class ARepository<TProvider> where TProvider : class 
    { 
     protected TProvider Provider { get; set; } 

     protected ARepository(TProvider provider) 
     { 
      if (provider == null) 
       throw new ArgumentNullException("provider"); 

      Provider = provider; 
     } 
    } 

    public abstract class ARepository<TProvider, TValidator> : ARepository<TProvider> where TProvider : class where TValidator : class 
    { 
     protected TValidator Validator { get; set; } 

     protected ARepository(TProvider provider, TValidator validator) : base(provider) 
     { 
      Validator = validator; 
     } 
    } 
} 
+4

取決於你想達到什麼 – Magnus 2012-08-16 20:04:43

+0

我想讓TValidator成爲可選項。 – CaffGeek 2012-08-16 20:28:58

+1

哇... 3個投票? ZERO解釋。 – CaffGeek 2012-08-16 20:30:34

回答

11

我不認爲你可以做到這一點作爲一個類,目前,一般我嘗試在這種情況下,做的是打造最普通類(即需要最通用的參數)讓所有邏輯,然後使更具體的是默認這些類型的子類。

例如,假設我們正在編寫一個從一種類型的值到另一個翻譯翻譯,因此喜歡的Dictionary但也有違約等

我們可以將此定義爲:

public class Translator<TKey, TValue, TDictionary> where TDictionary : IDictionary<TKey, TValue>, new(); 
{ 
    private IDictionary<TKey, TValue> _map = new TDictionary(); 
    ... 
} 

這是我一般情況下,可以有IDictionary任何實現,但說,我們要始終使用Dictionary如果沒有指定一個簡單的版本,我們可以這樣做:

public class Translator<TKey, TValue> : Translator<TKey, TValue, Dictionary<TKey, TValue>> 
{ 
    // all this does is pass on the "default" for TDictionary... 
} 

這樣,我可以做:

// uses Dictionary<int, string> 
var generic = new Translator<int, string>(); 

// uses SortedDictionary instead 
var specific = new Translator<int, string, SortedDictioanry<int, string>>(); 

所以你的情況,也許你一般總是有TValidator屬性,但它的默認(也許總是在最通用的形式返回true

例如,也許你有一個默認驗證(比如叫DefaultValidator),你可以扭轉你的定義,以便更通用的(即需要更多的泛型類型參數之一)擁有所有的邏輯和任何專業化的定義(較少的類型參數)只是子類默認這些額外的類型:

using System; 

namespace SnippetTool.Repositories 
{ 
    public class DefaultValidator 
    { 
     // whatever your "default" validation is, may just return true... 
    } 

    public abstract class ARepository<TProvider> : ARepository<TProvider, DefaultValidator> 
     where TProvider : class 
    { 
     protected ARepository(TProvider provider) : base(provider, new DefaultValidator()); 
     { 
     } 

     // needs no new logic, just any specialized constructors... 
    } 

    public abstract class ARepository<TProvider, TValidator> 
     where TProvider : class 
     where TValidator : class 
    { 
     public TValidator Validator { get; set; } 

     protected ARepository(TProvider provider, TValidator validator) 
     { 
      Provider = provider; 
      Validator = validator; 
     } 

     // all the logic goes here... 
    } 
} 

UPDATE:是的,根據您的意見,如果TValidator是一個附加的(而不是別的拖欠),然後像你一樣分層是適當的。

+0

問題是,在某些情況下我根本不需要TValidator,沒有默認值,我只是不想要它。但我總是需要一個TProvider。 – CaffGeek 2012-08-16 20:32:19

+1

@Chad:那麼你的代碼是一個很好的方法來做到這一點,我唯一的建議是儘量讓其中的一個類儘可能輕以避免重複的邏輯。 – 2012-08-16 21:05:46

+0

謝謝,這證實了我的想法。 – CaffGeek 2012-08-16 21:23:56