Reputation: 983
A little intro
Hello, I'm developing a WebApi Rest Service and currently I'm working on an endpoint which returns different dictionaries (arrays of entities, don't confuse with Dictionary
data type) in JSON format. Dictionaries can be retrieved by name: /dictionaries/:dictName
. The problem is that items kept in dictionaries can be of two types:
First type of entities
class Item {
public long ID { get; set; }
public string Name { get; set; }
}
Second type of entities - extended item
class ExtendedItem : Item {
public string AdditionalProperty { get; set; } // Let's name it this way just for example
}
The problem
I'd like to avoid sending AdditionalProperty
for dictionaries which don't need it.
Current solution
I've developed a simple method in ApiController:
public IHttpActionResult GetDict(string name)
{
try
{
object outDict = null;
switch(name) {
case "simpleDict":
IList<Item> simpleDict = _dataLayer.GetSimpleDict();
// ...
outDict = simpleDict;
break;
case "extDict":
IList<ExtendedItem> extDict = _dataLayer.GetExtDict();
// ...
outDict = extDict;
break;
// ... and a few more dictionaries
}
SomeLogger.SomeLogging(name, outDict);
return Ok(outDict);
}
catch (Exception ex)
{
// Just returning error
return BadRequest(ex.Message);
}
}
Conclusion and questions
Although I managed to find a solution for the problem, I'm not fully satisfied with it. Personally, I'd like to find a simple way to avoid using object
data type, however couldn't figure any. And now come the questions:
object
type. Is there any easy way to restrict IList to contain either Item or ExtendedItem and no other types? I'll be grateful for any help.
Upvotes: 0
Views: 813
Reputation: 2164
You could just return in the switch statement as well:
public IHttpActionResult GetDict(string name)
{
try
{
switch(name) {
case "simpleDict":
return Ok(_dataLayer.GetSimpleDict());
case "extDict":
return Ok(_dataLayer.GetExtDict());
}
SomeLogger.SomeLogging(name, outDict);
return Ok(new List<Item>());
}
catch (Exception ex)
{
// Just returning error
return BadRequest(ex.Message);
}
}
Upvotes: 0
Reputation: 12805
If you declare your outDict
variable as a collection instead of object
, then you'll be able to assign directly.
IEnumerable<Base> outDict = null;
switch(name) {
case "simpleDict":
IList<Item> simpleDict = _dataLayer.GetSimpleDict();
// ...
outDict = simpleDict;
break;
case "extDict":
IList<ExtendedItem> extDict = _dataLayer.GetExtDict();
// ...
outDict = extDict;
break;
// ... and a few more dictionaries
}
Upvotes: 1
Reputation: 4185
Try use Interface
to free up the implementation for ExtendedItem. Using Object for API return can be useful if you need Type dynamic to process things differently before sending back the callback response.
interface Item {
public long ID { get; set; }
public string Name { get; set; }
}
class SimpleItem : Item {
public long ID { get; set; }
public string Name { get; set; }
}
class ComplicateItem: Item {
public long ID { get; set; }
public string Name { get; set; }
public string AdditionalProperty { get; set; }
}
Then in the api controller,
Item outDict;
switch(name) {
case "simpleDict":
var simpleDict = _dataLayer.GetSimpleDict();
// ...
outDict = simpleDict;
break;
case "extDict":
var extDict = _dataLayer.GetExtDict();
// ...
outDict = extDict;
break;
// ... and a few more dictionaries
}
Upvotes: 0