Как правильно использовать дженерики и ограничения типов в этом сценарии? - PullRequest
0 голосов
/ 27 апреля 2018

Я запутался в обобщениях и ограничениях типов, я сразу перейду к делу.

У меня есть класс BaseQueryResult

public abstract class BaseQueryResult<T>
{
    public int Count => Models != null && Models.Any() ? Models.Count : 0;

    public Exception Exception { get; set; }

    public bool HasException => Exception != null;

    public bool IsSuccess => Exception == null;

    public bool NotFound { get; set; }

    public string ContinuationToken { get; set; }

    public IList<T> Models { get; set; }
}

Дочерний класс, который наследует от вышеупомянутого

public class TransportListingQueryResult : BaseQueryResult<TransportListingQueryModel>
{
    public TransportListingQueryResult(IList<TransportListingQueryModel> models, string continuationToken)
    {
        Models = models;
        ContinuationToken = continuationToken;
        NotFound = false;
    }

    public TransportListingQueryResult(Exception exception)
    {
        NotFound = false;
        Exception = exception;
    }

    public TransportListingQueryResult(bool notFound, Exception exception)
    {
        NotFound = notFound;
        Exception = exception;
    }

    public static TransportListingQueryResult NotFoundResult(Exception exception)
    {
        return new TransportListingQueryResult(true, exception);
    }
}

Мой метод расширения, который я использую

public static class TransportListingQueryResultExtension
{
    public static IActionResult ToActionResult<T>(this T result, ControllerBase controller, int limit, string routeName, object values, HttpStatusCode successStatusCode = HttpStatusCode.OK)
        where T : BaseQueryResult<T>
    {
        if (result.NotFound)
        {
            return controller.NotFound();
        }

        if (!result.IsSuccess)
        {
            if (result.HasException)
            {
                throw result.Exception;
            }

            return controller.BadRequest(new ErrorResponse { Messages = new[] { ErrorMessages.InternalServer } });
        }

        var uri = controller.Url.Link(routeName, values);
        var response = new HyperMediaResponse<T>(
            new LinkItem(uri),
            new PageItem(limit, result.ContinuationToken, result.Count),
            result.Models);

        switch (successStatusCode)
        {
            case HttpStatusCode.Created:
                return controller.Created(string.Empty, response);
            case HttpStatusCode.OK:
            default:
                return controller.Ok(response);
        }
    }
}

И, наконец, мое действие в моем контроллере

public async Task<IActionResult> Create([FromBody]CreateListingModel createListing)
    {
        var result = await _transportListingStore.CreateNewAsync(createListing);
        return result.ToActionResult<TransportListingQueryResult>(this, 1, Constants.RouteNames.CreateListing, null, HttpStatusCode.Created);
    }

Я получаю сообщение об ошибке в этой строке в моем действии вернуть результат. ToActionResult ( этот, 1, Constants.RouteNames.CreateListing, ноль, HttpStatusCode.Created );

Ошибка:

Тип 'TransportListings.API.Application.Response.TransportListingQueryResult' нельзя использовать в качестве параметра типа 'T' в универсальном типе или методе 'TransportListingQueryResultExtension.ToActionResult (T, ControllerBase, int, string, object, HttpStatusCode). Не существует неявного преобразования ссылок из «TransportListings.API.Application.Response.TransportListingQueryResult» в «TransportListings.API.Application.Response.BaseQueryResult»

Я в замешательстве, поскольку мой дочерний класс наследует BaseQueryResult, но ошибка говорит мне, что неявного преобразования ссылок не существует. Я не слишком уверен, что не так с моим кодом и почему он дает мне ошибку.

Любая помощь будет оценена. Заранее спасибо.

1 Ответ

0 голосов
/ 27 апреля 2018

Проблема в том, что ваше ограничение невозможно удовлетворить:

public static IActionResult ToActionResult<T>(this T result, /* snip */)
    where T : BaseQueryResult<T>

Где то, что вы действительно хотите, это что-то вроде:

public static IActionResult ToActionResult<T, U>(this T result, /* snip */)
    where T : BaseQueryResult<U>

И назовите это так:

return result.ToActionResult<TransportListingQueryResult, TransportListingQueryModel>(
    this, /* snip */);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...