Общий интерфейс C # с различными типами возвращаемых данных - PullRequest
6 голосов
/ 20 октября 2011

У меня есть веб-сервис, который может возвращать данные в нескольких форматах.Например, JSON и XML.Я создаю простой C # API для этого веб-сервиса и хотел бы, чтобы методы могли возвращать полностью сериализованные объекты из json, raw json или raw xml.Например:

List<Order> GetOrders(int customerId)
string GetOrders(int customerId)
XMLDocument GetOrders(customerId)

Customer GetCustomer(int customerId)
string GetCustomer(int customerId)
XMLDocument GetCustomer(int customerId)

У меня есть идея о создании свободного API, где вы бы вызвали метод SetFormat (), который бы затем возвращал общий интерфейс для вышеуказанных методов.Но я застрял на том, как будет выглядеть этот интерфейс, поскольку реализация, возвращающая сериализованные объекты, возвращает объекты разных типов.

Другое простое решение - просто иметь методы, возвращающие сериализованные объекты, а затем добавить выходПараматер, как это:

List<Order> GetOrders(int customerId, out string data)

но это не очень хорошее решение, я думаю ....

ОБНОВЛЕНИЕ

Я предпочел не универсальныйРешение, которое предложил Sjoerd, я слишком усложнил мою проблему.Вот что я в итоге сделал:

public class ServiceEntity {
    List<Order> GetOrders(int customerId)....
}    
public class ServiceJson {
    string GetOrders(int customerId)....
}
public class ServiceXml {
    XmlDocument GetOrders(int customerId)....
}

Затем беглый класс обслуживания, подобный этому:

public class Service : IService {
    ....
    public AsJson() { return new ServiceJson(); }
    public AsEntity() { return new ServiceEntity(); }
    public AsXml() { return new ServiceXml(); }
}

Используется так:

string json = Service.New().AsJson().GetCategories(1);
List<Order> = Service.New().AsEntity().GetCategories(1);

Спасибо за всеответы!

Ответы [ 6 ]

2 голосов
/ 20 октября 2011

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

Например, следующий класс:

public class OrderThingy 
{
    public static implicit operator List<Order>(OrderThingy orderthingy)
    {
        // Use CustomerId to get the data
        return new List<Order>();
    }

    public static implicit operator string(OrderThingy orderthingy)
    {
        // Use CustomerId to get the data
        return "string representation";
    }

    public static implicit operator XDocument(OrderThingy orderthingy)
    {
        // Use CustomerId to get the data
        return new XDocument();
    }

    private int CustomerId { get; set; }

    public OrderThingy GetOrders(int customerId)
    {
        CustomerId = customerId;
        return this;
    }
}

И вы можете использовать это так:

XDocument doc = new OrderThingy().GetOrders(1);
List<Order> orders = new OrderThingy().GetOrders(2);
string stringorders = new OrderThingy().GetOrders(2);
2 голосов
/ 20 октября 2011

Просто создайте общий возвращаемый класс

public class FormattedClass<T>
{
    List<T> ItemList { get; set; }
    string Json { get; set; }
    XmlDocument Document { get; set; }
}

public FormattedClass<T> GetItems<T>(long primaryKey)
1 голос
/ 20 октября 2011

Приятно пытаться использовать дженерики, но дженерики - это не серебряная пуля!

В этом случае мне интересно, сколько кода вы бы сэкономили по сравнению с неуниверсальным:

List<Order> GetOrdersAsList(int customerId)
string GetOrdersAsString(int customerId)
XMLDocument GetOrdersAsXml(customerId)

Бьюсь об заклад, почти никто!

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

List<Order> GetOrders(int customerId)
string OrdersToString(List<Order> orders)
XMLDocument OrdersToXml(List<Order> orders)

Затем последние два метода могут быть перемещены в отдельные классы, в результате чего ваш GetOrders() отсоединяется от формата.

Мне кажется, что этот подход намного лучше и чище, чем пытаться использовать дженерики в этом случае!

ОБНОВЛЕНИЕ : Не поймите меня неправильно, мне нравятся обобщения, и во многих случаях они делают код более читабельным. Несколько других ответов очень интересны, поскольку они показывают методы для достижения этой цели. Поэтому я рекомендую изучить их: они могут быть полезны в других случаях. Но в этом случае , каждое предлагаемое решение пока имеет практический недостаток. Вот почему я рекомендую не дженерики в этом случае.

1 голос
/ 20 октября 2011

как насчет дженериков?

T GetOrders<T>(int customerID)
1 голос
/ 20 октября 2011

Как насчет метода

private class WebService
{
    public T GetOrders<T>(int customerId)
    {
        if (typeof(T) == typeof(List<Order>))
        {
            return new List<Order>();
        }
        if (typeof(T) == typeof(string))
        {
            return "42";
        }
    }
}

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

var webService = new WebService();

var a = webService.GetOrders<List<Order>>();
var b = webService.GetOrders<string>();

, вы возвращаете ожидаемое значение.

0 голосов
/ 20 октября 2011

Возможно, инкапсулируйте различные типы возвращаемых данных в один общий тип:

CustomerResult GetCustomer(int customerId)

, где

CustomerResults имеет:

Get/SetFormat()
Get/SetCustomer()
Get/SetXmlDoc()
Get/SetString()

и т.д.

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