C # Common interface with various return types

I have a webservice that can return data in several formats. For example json and xml. I am creating a simple C # api against this webservice, and I would like the methods to be able to return either fully serialized objects from json, raw json or raw xml. For instance:

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

I have an idea about using api freely, where you would call the SetFormat () method, which would then return a common interface for the above methods. But I am fixated on what this interface will look like, since an implementation that returns serialized objects returns objects of different types.

Another simpler solution would be to simply use methods that return serialized objects, and then add an external parameter as follows:

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

but this is not a very pleasant solution, I think ....

UPDATE

I preferred the non-generic solution suggested by Sjoerd, I made my problem too complicated. This is what I ended up with:

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

Then a quick service class:

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

Used as follows:

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

Thanks for all the answers!

+6
source share
6 answers

It's nice to try using generics, but generics are not a silver bullet!

In this case, I wonder how much code you would save compared to non-generic:

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

I am sure that almost no!

And in case you decide not to have a general approach, most likely it will be internally:

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

Then the last two methods can be moved to separate classes, which will cause your GetOrders() not to be disconnected from the format.

It seems to me that this is a much better and cleaner approach than trying to use generics in this case!

UPDATE . Don't get me wrong, I like generics, and in many cases they make the code more readable. A few other answers are very interesting as they show methods for achieving this. Therefore, I recommend to study them: they can be useful in other cases. But in this case , each proposed solution still has a practical drawback. Therefore, I recommend using non-generics in this case.

+1
source

Just create a generic return class

 public class FormattedClass<T> { List<T> ItemList { get; set; } string Json { get; set; } XmlDocument Document { get; set; } } public FormattedClass<T> GetItems<T>(long primaryKey) 
+2
source

You can also take a look at using an implicit statement to return data as expected.

For example, the following class:

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

And you can use it as follows:

 XDocument doc = new OrderThingy().GetOrders(1); List<Order> orders = new OrderThingy().GetOrders(2); string stringorders = new OrderThingy().GetOrders(2); 
+2
source

What about the method

 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"; } } } 

and depending on the type that you provide on call, for example:

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

you return the expected value.

+1
source

what about generics?

 T GetOrders<T>(int customerID) 
+1
source

It is possible to encapsulate different types of returned data into one common type:

 CustomerResult GetCustomer(int customerId) 

Where

CustomerResults has:

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

and etc.

0
source

Source: https://habr.com/ru/post/899700/


All Articles