Как мне получить динамические свойства из OkObjectResult

#c# #anonymous-class

#c# #анонимный класс

Вопрос:

Я возвращаюсь IActionResult со значением анонимного объекта из метода контроллера.
Как мне снова получить данные?

Вот метод контроллера, сведенный к самой проблеме:

 [HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
    long size = file.Length;
    return Ok(new { count = 1, size });
}
 

Затем я получаю .Value свойство, которое является object и создает его dynamic .
Но нет, он не распознается.

 [Fact]
public async Task UploadFileTest()
{
    //  #   Given.
    var formFile = new Mock<IFormFile>();
    var sut = new HomeController(null);

    //  #   When.
    IActionResult result = await sut.UploadFile(formFile.Object);

    //  #   Then.
    OkObjectResult okResult = (OkObjectResult)resu< // Ok.
    dynamic dynValue = okResult.Value; // Ok.
    var count = dynValue.count; // Not ok.
}
 

Ожидаемый результат:

count должно быть 1.

Фактический результат:

Майкрософт.CSharp.RuntimeBinder.Исключение RuntimeBinderException: ‘object’ не содержит определения для ‘count’

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

1.Вы пробовали так => dynamic dynValue = okResult.Value as dynamic; ? ИЛИ dynamic dynValue = okResult.Value as ExpandoObject; ?

2. @er-sho Попытка приведения dynValue к dynamic ничего не даст, поскольку оно уже объявлено как a dynamic . Итак, при попытке приведения ко ExpandoObject всему, что происходит, это dynValue становится нулевым. dynamic и ExpandoObject это не одно и то же. Плюс за попытку.

Ответ №1:

Попробуйте отражение:

 var count = (int)okResult.Value.GetType().GetProperty("count").GetValue(okResult.Value);
 

Ответ №2:

Если ваш тестовый и исходный код не в одном проекте, если это так, вам нужно создать AssemblyInfo.cs в вашем исходном коде проект, чтобы он (оригинал) разделял структуру динамического объекта.

вы можете увидеть больше на https://sodocumentation.net/csharp/topic/4264/assemblyinfo-cs-examples#-internalsvisibleto —

Он должен иметь код, подобный приведенному ниже (замените строку в качестве имени вашего теста)

 [assembly: InternalsVisibleTo("MyAssembly.UnitTests")]