2012-08-16 2 views
14

더 좋은 방법이 있나요? 아마도 하나의 클래스로서, 2 대신에.선택 사항 일반 유형

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

와우 ... 3 가까운 표를 얻으시겠습니까? 제로 설명. – 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라고 말)을 기본 검증의 정의가 TValidator 애드온 (을 기본값 하지 뭔가) 인 경우, 예, 당신의 의견에 따라 :

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 : (적은 유형 매개 변수)는 그 여분의 유형을 기본적으로 단지 서브 클래스 당신처럼 적절하다.

+0

문제는, 어떤 경우에는 TValidator를 전혀 원하지 않는다는 것입니다. 기본값이 없기를 바랄뿐입니다. 그러나 나는 항상 TProvider가 필요합니다. – CaffGeek

+1

@Chad : 그럼 코드가 좋은 방법인데, 내 충고는 중복 논리를 피하기 위해 클래스 중 하나를되도록 가볍게 만드는 것입니다. –

+0

고마워, 그건 내가 생각한 것을 확인해 준다. – CaffGeek