可选的通用类型

Caf*_*eek 14 c# generics

有没有更好的方法来写这个?也许是一类,而不是两类.

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*are 11

我不认为你可以把它作为一个类来做,目前,我在这种情况下尝试做的一般是创建最通用的类​​(采用最通用的args的那个)来拥有所有的逻辑,然后做更多特定的是默认这些类型的子类.

例如,假设我们正在编写一个翻译器,它将一种类型的值转换为另一种类型,因此像a,Dictionary但也有默认值等.

我们可以将其定义为:

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

这是我的一般情况,它可以有任何实现IDictionary,但是我们想要一个更简单的版本,Dictionary如果没有指定总是使用,我们可以这样做:

public class Translator<TKey, TValue> : Translator<TKey, TValue, Dictionary<TKey, TValue>>
{
    // all this does is pass on the "default" for TDictionary...
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我可以:

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

// uses SortedDictionary instead
var specific = new Translator<int, string, SortedDictioanry<int, string>>();
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,也许你的泛型总是有一个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...
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:是的,根据你的评论,如果它TValidator是一个附加组件(而不是默认值),那么就像你所做的那样对它进行分层是合适的.