2012-08-16 108 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