Может ли свойство класса быть как T, так и IEnumerable <T>? - PullRequest
1 голос
/ 07 апреля 2020

Есть ли способ для свойства в классе принять оба значения T или IEnumerable<T> в качестве значения?

Я пытаюсь реализовать DTO для ответа об успешном выполнении API, где свойство Data может быть как одним JSON объектом, так и совокупностью JSON объектов. Есть ли способ использовать один отдельный класс для достижения этого или мне нужно иметь два класса, один для T и другой для IEnumerable<T>?

Вот мой код:

public class ApiClass<T> where T : class, IEnumerable<T>
{
    public ApiClass(IEnumerable<T> data)
    {
        Data = data;
        Message = "Enumerable data received";
    }

    public ApiClass(T data)
    {
        Data = data;
        Message = "Object data received";
    }

    private IEnumerable<T> Data { get; set; }

    private string Message{ get; set; }
}

И вот результат, который я намереваюсь получить после сериализации экземпляра объекта:

{
  "data": {
    "Id": 1,
    "Name": "John"
  },
  "message": "Object data received."
}

или

{
  "data": [
    {
      "Id": 1,
      "Name": "John"
    },
    {
      "Id": 2,
      "Name": "Mary"
    }
  ],
  "message": "Object data received."
}

Этот код компилируется, однако я получаю следующее сообщение об ошибке, когда Я пытаюсь создать новый объект как в return new ApiClass<User>(new User());:

Error: CS0311 - The type 'XPTO.User' cannot be used as type parameter 'T' in the generic type or method 'ApiClass<T>'. There is no implicit reference conversion from 'XPTO.User' to 'System.Collections.Generic.IEnumerable<XPTO.User>'.

Ответы [ 2 ]

3 голосов
/ 07 апреля 2020

Используйте несколько классов и позвольте программисту решить, от какого из них унаследовать результат, который им нужен. Например:

public class ApiClass
{
    public string Message{ get; private set; }
}

public class ApiClass<T> : ApiClass where T : class
{
    public ApiClass(T data)
    {
        Data = data;
        Message = "Object data received";
    }

    public T Data { get; private set; }
}

public class ArrayApiClass<T> : ApiClass where T : class
{
    public ArrayApiClass(IEnumerable<T> data)
    {
        Data = data;
        Message = "Enumerable data received";
    }

    public IEnumerable<T> Data { get; private set; }
}
2 голосов
/ 07 апреля 2020

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

Вместо этого имейте свойство с именем "MainData" или что-то еще, если коллекции нет. В противном случае люди предпочли бы просто получить первый элемент в массиве, если есть контракт, в котором всегда должна быть коллекция.

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