Передача класса данных в качестве переменной в функцию

1

Я пытаюсь создать модуль повторного использования для вызовов API в С#. Я хочу использовать это для нескольких API. Но мне трудно переносить мои классы данных динамически, как переменную в мою функцию, которая обрабатывает вызовы API.

Скажем, например, что я называю два совершенно разных API, мы будем называть их "Api # 1" и "Api # 2". И у меня есть следующие классы:

// This is the format of the response from Api #1 GET
public class Api01Get
{
    public int orderId { get; set; }
    public DateTime orderDate { get; set; }
}

// This is the format of the response from Api #2 GET
public class Api02Get
{
    public bool isGreen { get; set; }
    public string name { get; set; }
}

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

var result = CallAPI<Api02Get>(baseAddress, requestUri);

Но это не дает мне гибкости, которой я пользуюсь.

Вот определение моей функции (здесь я оставил другие параметры, которые не влияют на вещи):

private async Task<TResult> CallAPI<TResult>(Uri baseAddress, string requestUri)
{
    using (var client = new HttpClient()) 
    {
        client.BaseAddress = baseAddress;
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        HttpResponseMessage response = new HttpResponseMessage();
        response = await client.GetAsync(requestUri);
        if (response.IsSuccessStatusCode)   
        {
            TResult result = await response.Content.ReadAsAsync<TResult>();
        }
    }

    // do other stuff...

    return result;
}

Теперь это то место, где меня повесили. Я должен думать об этом неправильно, но то, что я пытаюсь сделать, это что-то вроде этого, например:

object apiModel;

switch (whichAPI)
{
    case "API_01_GET":
        apiModel = new Api01Get();
        break;

    case "API_02_GET":
        apiModel = new Api02Get();
        break;

    // Other cases...

    default:
        break;
}    

var result = CallAPI<apiModel>(baseAddress, requestUri);

При попытке последней строки я получаю сообщение об ошибке. "Тип или имя пространства имен" apiModel "не удалось найти (вы не указали директиву использования или ссылку на сборку?)". Я пробовал другие вещи, но это версия, которая показалась мне самой близкой, поэтому я опубликовал ее.

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

  • 0
    Это не поможет вашей проблеме с дизайном, но причина, по которой вы получаете эту ошибку, заключается в том, что apiModel - это не тип, а объект. Попробуйте apiModel.GetType() . (Я не уверен на 100%, что будет работать)
  • 2
    Если бы вы могли заставить это скомпилировать и работать как написано, что будет дальше? Вы все еще не знаете во время компиляции тип объекта, на который указывает result переменная, поэтому вы не можете ничего с этим сделать.
Показать ещё 2 комментария
Теги:

1 ответ

0
Лучший ответ

К сожалению, вы не можете использовать generics здесь без дополнительного отражения для динамического вызова CallAPI<T>.

К счастью, HttpContentExtensions имеет дополнительные перегрузки, которые позволят вам передать Type. Вам просто нужно перегрузить ваш метод и внести незначительные изменения в ReadAsAsync.

private async Task<object> CallAPI(Uri baseAddress, string requestUri, Type apiType)
{
    using (var client = new HttpClient()) 
    {
        ....

        if (response.IsSuccessStatusCode)   
        {
            object result = await response.Content.ReadAsAsync(apiType);
        }
    }

    ....

    return result;
}

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню