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

+0

Я хочу, чтобы TValidator был необязательным. – CaffGeek

+1

Wow ... 3 закрыто голосов? ZERO объяснения. – CaffGeek

ответ

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

+1

@Chad: Тогда ваш код - хороший способ сделать это, мой единственный совет - попытаться сделать один из классов максимально легким, чтобы избежать дублирования логики. –

+0

Спасибо, что подтверждает то, что я думал. – CaffGeek

Смежные вопросы