Filling list with different types of objects
Asked Answered
M

3

3

I'm working on a recommendation algorithm which all works fine. But now I wanted to implement this code into the branch of my development team.

I'll start from the top. My algorithm can recommend 2 types of objects, restaurants and dishes.

Restaurant:

public class Restaurant
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
    public List<Tag> Tags { get; set; } = new List<Tag>();
    public int PriceRange { get; set; }
}

And dish:

public class Dish
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public virtual Restaurant rest { get; set; }
    [ForeignKey("rest")]
    public Guid RestaurantId { get; set; }
    public List<Tag> Tags { get; set; }
}

Now my product owner wants the list to be like this when it's being presented on the home page of our app:

[Restaurant][Dish][Restaurant][Dish] Etc...

So basically, he wants to alternate the type of object that's being recommended. These dishes and restaurants are completely separate. They are generated by my algorithm purely on the user's preferences and have no correlation with eachother at all.

Now my problem is how to return such a list. I figured I'd need a wrapper class which contains either a Restaurant or Dish like this:

public class RecommenderItem
{
    public Restaurant rest { get; set; }
    public Dish dish { get; set; }
}

This way I can create a List<RecommenderItem> and return that to the client. The client would only need to check which attribute is null and retrieve the values from the one that is not.

I'm just unsure if this is the correct approach. Are there any 'best practices' in doing this? Let me know if I should elaborate more!

Melo answered 13/12, 2016 at 14:54 Comment(11)
Personally I'd have both classes implement an interface which exposes shared properties, such as Id and Name (and e.g. Tags) and create a list of that interface (the interface could also expose a 'Type' for the alternation)Coriander
RecommenderItem sounds like exactly the right solution to me, since it appears that it's a list of dishes, each of which is associated with a restaurant. Your return type should reflect that, as it does.Azoic
@Coriander but the client wants to show all data from each object, wouldn't that cause issues?Melo
@EdPlunkett so it's totally fine to check if an attribute is null and use the one that's not? It just seemed a little... off to meMelo
Depends how you generate the display information. e.g. the ToString() could return all relevant information or the interface could expose something like 'ListProperties'Coriander
@Coriander makes sense, thanks a lot!Melo
@Bas Whoops -- I missed that para in your question. Each pair of [Restaurant, Dish] is one instance of RestaurantItem. Every RestaurantItem is a tuple of a Dish, and the Restaurant where that dish is served. At least that's what I inferred from what you're saying. My understanding is that this is not a list where any given element could randomly be either a restaurant or a dish, but rather a list of restaurant-dish pairs.Azoic
@EdPlunkett no, the dish and restaurant are completely separate. All recommendations are generated purely based on the user's preferences. My product owner just wanted alternated recommendations on the home page.Melo
@Bas Ah, OK. Sorry. Even then, though, it's perfectly fine to have one property or the other be null. Usually better than a List<Object> where anything could be in there -- unless the UI lets you use some kind of data template mechanism, where it'll dynamically choose the right template to display the item. Then go with List<Object>, or List<WhateverBaseClass>. I'd change your example to [Restaurant][Dish][Restaurant][Restaurant][Dish] or something to make that clear. (OTOH nobody but me missed your point, so maybe you're fine!)Azoic
@EdPlunkett well it's [Restaurant][Dish][Restaurant][Dish], which is exactly what my product owner wants. I'll add a description to explain it better.Melo
@Bas Ohhh, god I'm slow this morning. So it explicitly alternates, but they're not pairs. I like the answer you picked.Azoic
B
2

If they doesn't have common base class then creating one wrapper class is the best solution. At the same time you can be more flexible and create something like

public class RecommendationItem
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string PageUrl { get; set; }
    public object Entity { get; set; }
}

So you can include all common information in this class and client will not be required to check with which object type he works. In such case it would be easier to add one more item type. At the same type I added reference to entity itself - it can be used if some specific handling for one or two item types is required.

Bullheaded answered 13/12, 2016 at 15:1 Comment(1)
Ah, so I would have to check which type Entity is and use it accordingly?Melo
P
1

You can declare an interface IRecommenderItem:

public interface IRecommenderItem
{
    //shared properties
}

public class Restaurant : IRecommenderItem
{

}

public class Dish : IRecommenderItem
{

}

than, you can type:

List<IRecommenderItem> m = new List<IRecommenderItem>();
Propagandism answered 13/12, 2016 at 15:12 Comment(0)
T
0

If you are going to connect pairs of elements it always makes sense to me to... well, pair the elements. I am assuming that each dish is specific to a particular restaurant? So the list would be [Restaurant1][Dish for Restaurant1][Restaurant2][Dish for Restaurant2]...?

I like the previous answer by oryol creating a common base class as well.

So, your RecommenderItem class is fine. But fill in both properties and pass a list of pairs back. Expand the list into the full set of items for display by creating a new List, iterating through the list of RecommenderItems and adding Restaurant and Dish from each entry in it.

Thermistor answered 13/12, 2016 at 15:7 Comment(2)
They aren't pairs though. The dishes and restaurants are completely separate. My algorithm generates these recommendations purely on the information from the user. My product owner only wanted to alternate the types on the home page of the user.Melo
Ah! Well that's what I get for second guessing!Thermistor

© 2022 - 2024 — McMap. All rights reserved.