Question

I'm trying to use a single view model to display various item types as links on a page. For example TeamMembers, NewsItems, Articles etc.

I have 4 x item>VM mappings that cover 12 item types. (For example the subtitle for NewsItems will be publish date, for TeamMembers it will be their position in the company.)

I'm considering 3 options, but none of them feel very elegant to me. Would anyone with more experience be able to guide me in the right direction?

The ViewModel

public class ItemLink
{
    public string Title { get; set; }
    public string SubTitle { get; set; }
    public string Image { get; set; }
}

public class LinkSet
{
    public List<ItemLink> Links {get;set;}

    public LinkSet(IEnumerable<NewsOrArticlesOrTeamMembers>, myEumerable)
    {
        // mapping here 
    }
}

Option 1

Create a constructor for each item type. That would give me 12 constructors for 4 sets of mappings, which doesn't seem very DRY.

Option 2

Create an Item > VM mapping class with the 3 options. Choose which option to use when instantiating the VM. This feels like it's introducing unnecessary complexity into the application.

Option 3*

Give the VM constructor of the a dynamic argument, test for type inside the constructor and choose the appropriate mapping accordingly. This would be my only use of Reflection in the whole application, so I'd rather not use it if possible.

Was it helpful?

Solution

If I understand the problem correctly, one way to go would be to introduce an interface like the following:

interface IItemLinkProvider
{
     string GetTitle();
     string GetSubtitle();
     string GetImage();
}

You can implement this interface with all the classes you'd like to support. Thus you can modify the constructor of your LinkSet like this:

public class LinkSet
{
    public List<ItemLink> Links { get; set; }

    public LinkSet(IEnumerable<IItemLinkProvider> items)
    {
        Links = items.Select(i => new ItemLink
            {
                Title = i.GetTitle(),
                Subtitle= i.GetSubtitle(),
                Image = i.GetImage()
            }).ToList();
    }
}

This way you can decouple your LinkSet view model from the concrete model types, and can make it only depend on the abstraction (the IItemLinkProvider interface), which is always a good thing.

(Note that you are going to need C# 4.0 to use this constructor properly because covariance of generic interfaces has been introduced in C# 4.0)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top