REST Web API: JSON до C# Объект основан на пути запроса - PullRequest
1 голос
/ 21 января 2020

У меня есть приложение C#, которое запрашивает REST Web API.

Запросы возвращают JSON объектов. Я пытаюсь (не) маршалировать эти объекты до C#. Я использую библиотеку System.Text. Json для выполнения (не) маршалинга. Различные пути запроса возвращают разные типы объектов, и у меня есть словарь, который используется для определения того, какой тип данных мы должны ожидать, основываясь на используемом пути запроса.

public static class ModelTypes
{
    private static Dictionary<string, Type> all = new Dictionary<string, Type>()
    {
        { "achievements", typeof(List<Achievement>) }
    };
    public static Type GetTypeFromPath(string path)
    {
        if (all.ContainsKey(path)) return all[path];
        else return null;
    }
}

Затем у меня есть другой класс который содержит клиент имени объекта HttpClient. Я написал функцию, которая выполняет стандартный запрос GET к API и возвращает объект C# типа T, указанный при вызове функции.

public async Task<T> Get<T>(string path)
{
    Task<Stream> streamTask = client.GetStreamAsync(path);
    return await JsonSerializer.DeserializeAsync<T>(await streamTask);
}

Затем в приложении я хочу фактически вызвать эту функцию , но я не могу заменить тип, возвращенный функцией GetTypeFromPath () для T.

string path = "achievements";
Type type = ModelTypes.GetTypeFromPath(path);
if (type != null)
{
    var result = await api.Get<type>(path); // <--- Red squiggly under "type"
}
else ...

Если я жестко кодирую в типе, например:

var result = await api.Get<List<Achievement>>(path);
foreach (Achievement achievement in result) 
{ 
    Console.WriteLine(achievement.Name);
}

Все выполняет как и ожидалось, консоль распечатывает имя для каждого достижения в списке.

Любой совет, как мне просто использовать обобщенный c Get (путь строки)? Как динамически определить, что такое T, в отличие от жесткого кодирования? Возможно, есть лучший способ сделать это ...

1 Ответ

0 голосов
/ 21 января 2020

После этого я понял, что вы пытаетесь десериализовать вашу строку в тип, который вы определяете в Type.

    public async Task<T> Get<T>(string path)
    {
        Task<Stream> streamTask = client.GetStreamAsync(path);
        return (T)await JsonSerializer.DeserializeAsync(await streamTask, typeof(T));
    }

Вместо определения T как TValue в DeserializeAsync, вы должны передать Type в качестве аргумента методу. Кроме того, поскольку этот метод возвращает объект, вы также должны привести его к возвращаемому типу в вашем выражении возврата.

...