michaelw
michaelw

Reputation: 53

Generic List inside List with Interface

i'm currently working on a REST service, that creates pages and links in my CMS (Orchard), both of which need to be placed inside my menu.

This is my current solution:

public class ConfigurationDTO
{
    public ShellSettings Tenant { get; set; }
    public SetupContext SetupContext { get; set; }
    public IList<IList<Page>> Pages { get; set; }
    public IList<IList<Link>> Links { get; set; }

    public ConfigurationDTO() { }
}

My Page.cs

public enum PageType
{
    HomePage,
    DownloadPage,
    StandardPage
}

public class Page
{
    public PageType Type { get; set; }
    public string MenuText { get; set; }
    public string Title { get; set; }
    public string Text { get; set; }
    public string Culture { get; set; }
    public bool Publish { get; set; }

    public Page() { }
}

Link.cs

public class Link
{
    public string Url { get; set; }
    public string MenuText { get; set; }
    public string Culture { get; set; }
}

I have two lists containing other lists. The inner lists contain localization items (english, german and french versions of the same content item).

Most of my "meta" code is the same for both links and pages, which is why i refactor my code.

This is my refactoring attempt (not working):

public interface IItem

public class Page : IItem

public class Link : IItem

My new List

public IList<IList<IItem>> Items{ get; set; }

What i'm aiming for:

foreach (var item in config.Items)
        {
            foreach (var translation in item)
            {
                var page = translation as Page;
                if (page != null) doSomething();

                var link = translation as Link;
                if (link != null) doSomethingElse();
            }
        }

Is there a way to get a specific implementation out of this list (meaning if it's a page, create a new page entry and vice versa)?

EDIT: I wrote a small sample program with the same principle and it works, meaning my problem lies somewhere else.

You can tell that this is my first post on stackoverflow because i just told you what isn't working and not what the actual problem is. My problem is that the order in my main menu is wrong:

What i want: Page1 | Page2 | Link1 | Page 3

What i get: Page1 | Page2 | Page3 | Link1

My code creates all the pages, then the links and adds them to the menu. Workaround -> every item has an order property. I might change it in the future so that i only need one list, but for now my workaround will have to suffice.

Anyway thanks to everyone.

Upvotes: 0

Views: 284

Answers (2)

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62498

You can use SelectMany() to flatten List of List in to a single list and then filter specific type with OfType<T>() this way:

var items = config.Items.SelectMany(x=>x);

var links = items.OfType<Link>();
var pages = items.OfType<Page>();

Upvotes: 2

Ben Reich
Ben Reich

Reputation: 16324

You might consider using the Linq method OfType to filter a generic list to the subset of the list that is of the desired type:

var pages = config.Items.OfType<Page>();
var links = config.Items.OfType<Link>();

You can read the documentation of OfType here.

Upvotes: 0

Related Questions