15

これを書く良い方法はありますか?おそらく、2 つではなく 1 つのクラスとして。

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

1 に答える 1

13

私はあなたが1つのクラスとしてそれを行うことができるとは思わない.現在、この状況で私がやろうとしているのは、最も一般的なクラス(最も一般的な引数をとるクラス)を作成してすべてのロジックを持ち、それからより多くの特定のものは、それらのタイプをデフォルトにするサブクラスです。

たとえば、あるタイプの値から別のタイプの値に変換するトランスレータを書いているとしましょう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...
    }
}

更新:はい、あなたのコメントに基づいて、TValidatorがアドオンである場合(デフォルトのものではない場合)、あなたがしたようにそれをレイヤー化することが適切です。

于 2012-08-16T20:14:19.167 に答える