用通用方法实现通用接口

时间:2018-12-14 10:24:50

标签: c# generics

我的界面如下:

public interface IService<T> where T : class
{
    Task<IEnumerable<T>> GetAsync<U>(int subscriberId, U request) where U : SearchRequestBase;
}

我正在实现以下方式(CategoriesRequest继承SearchSearchBase):

public async Task<IEnumerable<CategoriesResponse>> GetAsync<CategoriesRequest>(int subscriberId, CategoriesRequest request)
{
    // Implementation
}

但是无论我做什么,我都会遇到编译错误,使其起作用的唯一方法是将U泛型放入接口并在其中施加约束。

这是推荐的方法吗?还是可以在方法旁边声明具有约束的通用方法并以这种方式实现?

我的意图是仅将泛型作为返回类型,并且我的输入必须包含从SearchRequestBase继承的任何内容。

更新

这是我的基类:

public class SearchRequestBase
{
    private const int minimumQueryLength = 3;
    private const int minimumResultsSize = 1;
    private const int maximumResultsSize = 100;
    private const int defaultResultsSize = 5;

    protected SearchRequestBase()
    {
    }

    [Required]
    [MinLength(minimumQueryLength, ErrorMessage = "Query string has to contain at least three characters")]
    public string Query { get; set; }

    [Range(minimumResultsSize, maximumResultsSize, ErrorMessage = "Size must be between 1 and 100")]
    public int Size { get; set; } = defaultResultsSize;
}

还有CategoriesRequest类,该类现在尚未实现任何额外的属性(但会实现)。

public class CategoriesRequest : SearchRequestBase
{
}

从SearchRequestBase继承的请求更多。

所以现在有了我的IService界面:

public interface IService<T> where T : class
{
    Task<IEnumerable<T>> GetAsync(int subscriberId, SearchRequestBase request);
}

我在CategoryService中实现它:

public class CategoryService : IService<CategoriesResponse>
{
    private readonly IElasticClient _client;

    public CategoryService(IElasticClient client)
    {
        _client = client ?? throw new ArgumentNullException(nameof(client));
    }

    public async Task<IEnumerable<CategoriesResponse>> GetAsync(int subscriberId, CategoriesRequest request)
    {
        var descriptor = new CategoryBuilder().Build(subscriberId, request);

        var index = "categories";

        var response = await _client.SearchAsync<CategoriesResponse>(descriptor.Index(index));

        return response.Documents;
    }
}

但是编译器骂我,并给出以下错误:

Error   CS0535  'CategoryService' does not implement interface member 'IService<CategoriesResponse>.GetAsync(int, SearchRequestBase)'

1 个答案:

答案 0 :(得分:2)

您的方法签名必须为:

public async Task<IEnumerable<CategoriesResponse>> GetAsync(
    int subscriberId, SearchRequestBase request)

否则,您需要向接口添加另一个泛型类型参数。例如:

public interface IService<TRequest, TResponse>
    where TRequest : SearchRequestBase
    where TResponse : class
{
    Task<IEnumerable<TResponse>> GetAsync(int subscriberId, TRequest request);
}