繁体   English   中英

具有不同返回类型的C#通用接口

[英]C# Generic Interface with different return types

我有webservice,可以返回多种格式的数据。 例如json和xml。 我正在构建一个简单的C#api来对付这个web服务,我希望这些方法能够从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()方法,然后返回上述方法的通用接口。 但我仍然坚持该接口的样子,因为返回序列化对象的实现返回不同类型的对象。

另一个更简单的解决方案是只返回返回序列化对象的方法,然后像这样添加一个out参数:

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

但我认为这不是一个很好的解决方案....

UPDATE

我更喜欢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);

感谢所有的答复!

只需创建一个通用的返回类

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

public FormattedClass<T> GetItems<T>(long primaryKey)

您还可以查看使用隐式运算符按预期返回数据。

例如以下类:

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);

尝试使用仿制药很好,但仿制药不是银弹!

在这种情况下,我想知道与非泛型相比你会节省多少代码:

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()与格式分离。

在我看来,这比在这种情况下尝试使用泛型更好更清洁!

更新 :不要误解我的意思,我喜欢泛型,在很多情况下,它们使代码更具可读性。 其他几个答案非常有趣,因为它们展示了实现这一目标的技术。 所以我建议研究它们:它们可能在其他情况下很有用。 但是在这种情况下 ,到目前为止每个提出的解决方案都有实际缺陷。 这就是我在这种情况下推荐非泛型的原因。

怎么样的方法

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>();

你返回预期的价值。

仿制药呢?

T GetOrders<T>(int customerID)

也许将不同的返回类型封装到一个公共类型中:

CustomerResult GetCustomer(int customerId)

哪里

CustomerResults有:

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

等等

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM