Я использую API, обеспечивающий эту операцию:
[HttpGet]
[SwaggerOperation(OperationId = nameof(GetUsers))]
[SwaggerResponse(StatusCodes.Status200OK, "Result", typeof(List<UserModel>))]
[ProducesResponseType(typeof(List<UserModel>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ErrorModel), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> GetUsers(string tenantId, int departmentId)
{
// Magically queries the users and returns OK or detect something is wrong and returns BadRequest
...
}
Этот вызов может вернуть список UserModel
, если все в порядке, или ErrorModel
, если запрос неправильный.
Используя swagger
и autorest
, я получаю автоматически сгенерированный клиент, который имеет этот метод, возвращающий объект:
public async Task<HttpOperationResponse<object>> GetUsersWithHttpMessagesAsync(string tenantId, int departmentId, string commitReference = default(string), Dictionary<string, List<string>> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken))
{
...
}
В этом методе алгоритм проверяет код состояния.Если код состояния равен 200, он создает список UserModel
:
// Deserialize Response
if ((int)_statusCode == 200)
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
_result.Body = SafeJsonConvert.DeserializeObject<List<UserModel>>(_responseContent, DeserializationSettings);
}
catch (JsonException ex)
{
_httpRequest.Dispose();
if (_httpResponse != null)
{
_httpResponse.Dispose();
}
throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
}
}
Однако, если код состояния равен 400, создается экземпляр ErrorModel
:
if ((int)_statusCode == 404)
{
_responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
try
{
_result.Body = SafeJsonConvert.DeserializeObject<ErrorModel>(_responseContent, DeserializationSettings);
}
catch (JsonException ex)
{
_httpRequest.Dispose();
if (_httpResponse != null)
{
_httpResponse.Dispose();
}
throw new SerializationException("Unable to deserialize the response.", _responseContent, ex);
}
}
Поэтому, всякий раз, когда я использую этот метод, я должен проверять тип возвращаемого объекта, чтобы выяснить, есть ли у меня список UserModel
или ErrorModel
.
Я должен сделать что-то вроде этого, когда я вызываю автоматически сгенерированный клиент:
object result = await client.GetUserAsync(tenantId, departmentId);
switch (result)
{
case List<UserModel> userModels:
// Handle the users.
case ErrorModel errorModel:
// Handle the error.
}
Это вызывает любые проверки безопасности типов во время выполнения, а не во время компиляции, что, в свою очередь, может привести к ошибкам,
Вопрос
Как мне справиться с этой ситуацией в C #, не полагаясь на проверки типов во время выполнения?