Как правильно использовать обобщения и типы ограничений в этом сценарии?

Меня путают с дженериками и ограничениями типа, я буду прямо разбираться.

У меня есть класс 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; }
}
</t></t>

Детский класс, который наследует

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);
 }
}
</transportlistingquerymodel></transportlistingquerymodel>

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

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);
 }
 }
}
</t></t></t>

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

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);
 }
</transportlistingqueryresult></iactionresult>

Я получаю сообщение об ошибке в этой строке в моем возврате результата action.ToActionResult (это, 1, Constants.RouteNames.CreateListing, null, 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'

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

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

1 ответ

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

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</t,>

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

return result.ToActionResult<transportlistingqueryresult, transportlistingquerymodel="">(
 this, /* snip */);
</transportlistingqueryresult,>

licensed under cc by-sa 3.0 with attribution.