Приведение объекта к ожидаемому типу с помощью ‘as’ возвращает null

#c# #casting #asp.net-core-webapi

#c# #Кастинг #asp.net-core-webapi

Вопрос:

Приведение public object Parameters { get; set; } к ожидаемой структуре объекта request.Parameters as ParametersForA возвращает нуль.

Я попытался сериализовать request.Parameters и десериализовать его в ParametersForA тип с использованием Newtonsoft.Json , что отлично работает, но это все еще не удовлетворяет меня, поскольку я хотел бы понять предыдущий сбой.

Это код, который я тестирую:

C#

 using Microsoft.AspNetCore.Mvc;

namespace ObjectCasting.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        [HttpPost]
        public IActionResult Post([FromBody]Request request)
        {
            if (request.OperationCode == "A")
            {
                var obj = request.Parameters as ParametersForA; // <<< null problem
                return Ok(obj);
            }
            return BadRequest();
        }
    }

    public class Request
    {
        public string OperationCode { get; set; }
        public object Parameters { get; set; }
    }

    public class ParametersForA
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }
}
 

и это тело запроса HTTP POST json:

json

 {
    "OperationCode": "A",
    "Parameters": {
        "Age": 25,
        "Name": "Caroline"
    }
}
 

Я хочу понять, почему приведение здесь не работает.

Для указанного, уникального OperationCode в будущем я буду ожидать разные назначения приведения и Parameters структуру запроса json соответственно.

запрос

Комментарии:

1. Почему бы вам не определить свойство Parameters как ParametersForA . Почему он определен как object?

2. request.Parameters кажется, a JToken . Какой тип указывает отладчик? Та часть, которую вы только что вырезали из скриншота.

3. Для указанного, уникального OperationCode в будущем я буду ожидать различные назначения приведения и параметры структуры запроса json соответственно.

4. @Patrick Hofman request.Parameters.GetType в первой строке POST methot указывает Newtonsoft.Json.Linq.JObject тип.

5. Итак, как вы ожидаете, что это будет ParametersForA ?

Ответ №1:

Проблема заключается в типе Parameters свойства. Это object и фактический тип JObject , когда получен запрос.

Вы должны использовать ToObject<SomeType>() метод для приведения JObject к нужному типу:

 var obj = (request.Parameters as JObject).ToObject<ParametersForA>();
 

Для приведения к разным типам на основе OperationCode :

 switch(request.OperationCode)
{
    case "1":
       // cast to one type and process
    case "2":
       //cast to another type and process
}
 

Комментарии:

1. Да, я не ожидаю, что буду привязан к указанному типу, как вы предлагаете @Roman Doskoch

2. это то, что я искал! Только одна вещь, чтобы сделать код компилируемым var obj = ((JObject)request.Parameters).ToObject<ParametersForA>(); .

Ответ №2:

Приведение следует определенным правилам, для ссылочных типов должна быть иерархия, чтобы можно было преобразовать один тип в другой.

В вашем случае вы не можете его привести, потому что ваш Parameter фактически является a JToken , который не может быть приведен непосредственно ParameterA .

Согласно документации:

Неявные преобразования: специальный синтаксис не требуется, поскольку преобразование является типобезопасным и данные не будут потеряны. Примеры включают преобразования из меньших в большие целочисленные типы и преобразования из производных классов в базовые классы.

Комментарии:

1. @PatrickHofman Плакат просто хочет знать, почему приведение (преобразование) не работает. Это то, что объясняется здесь .

2. Тогда, возможно, он должен, и как только он это сделает, он сможет выяснить, как заставить это работать (или обойти это).

3. @peeyush singh, ваш пост также был ценным, поскольку он напомнил мне основное правило, которое я забыл в пылу битвы.

4. @PatrickHofman возможно, для вас это не имеет значения. Вы можете отметить мой ответ закрытым, если считаете, что он не дает никакой ценности, вместо того, чтобы протестовать и спрашивать, почему люди видят в нем ценность.

5. @peeyushsingh, сейчас нет значения. Но если вы добавите к нему небольшое объяснение (чтобы оно выглядело как ответ) — будет значение. Т.е. «Вы не можете привести его, потому что ваш параметр на самом деле является JToken, который нельзя напрямую привести к ParameterA. Вот документы: »