4

I am trying to build a dashboard that allows a variety of widgets to be displayed on the home screen. They are structured as follows:

public abstract class Widget {}
public abstract class GraphWidget : Widget {}
public class PieWidget : GraphWidget : Widget {}
public class BarWidget : GraphWidget : Widget {}
public class TextWidget : Widget {}

I wanted to give my viewmodel an IENumerable<Widget> Widgets {get;set;} property so that I can loop through them on the dashboard and display them properly. Since I am using JavaScript to display the graphs, the type of graph determines the JavaScript that will be output.

Is there a way to loop through all the widgets, but determine what type of widget it is?

5
  • define a method in the widget that the subclasses implement, e.g. public abstract class Widget { public void Display() }
    – Caleth
    Commented May 22, 2015 at 13:02
  • If I do that, that means the Display() method will generate the JavaScript. While this is doable, I'd rather not have Javascript hardcoded into the class. But that is definitely an option.
    – appsecguy
    Commented May 22, 2015 at 13:15
  • well you could expose is as an IWidgetDisplayRepresentation that your Javascript writer consumes
    – Caleth
    Commented May 22, 2015 at 13:18
  • You could construct a parallel hierarchy of javascript generating classes and then use a dictionary or other "linking" mechanism to first register and later select the correct javascript generating class for each widget class. ("Is there a way to loop through all the widgets, but determine what type of widget it is?" - TypeOf() method?) Commented May 22, 2015 at 17:49
  • See these related questions (and my answers) programmers.stackexchange.com/q/284314/41811 and programmers.stackexchange.com/q/280513/41811
    – Mike Nakis
    Commented May 22, 2015 at 20:46

2 Answers 2

5

If you want to separate the java script creation from your widgets you could also use the visitor pattern:

public interface IWidgetVisitor
{
    public void Visit(PieWidget widget);
    public void Visit(BarWidget widget);
    public void Visit(TextWidget widget);
    ...
}

public abstract class Widget
{
    public abstract void Accept(IWidgetVisitor visitor);
}

public class SomeWidget : Widget 
{
    public override void Accept(IWidgetVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class WidgetToJavaScriptConverter : IWidgetVisitor
{
    public void Visit(PieWidget widget)
    {
        // Do your conversion here
    }

    public void Visit(BarWidget widget)
    {
        // Do your conversion here
    }

    public void Visit(TextWidget widget)
    {
        // Do your conversion here
    }
    ...
} 
1
  • +1 for the overload approach, but your WidgetToJavaScriptConverter instance could be called from a simple loop without the added indirection of a visitor pattern. Commented May 22, 2015 at 17:54
0

Of course you can. You can use the is keyword to check if an item in the list is of a certain subtype. This is usually an anti-pattern.

Or you can implement a method in each subtype that returns an identifier that you will use to decide what to do with that item.

Or the method for each subtype can do whatever you deem desirable that will bring about the required functionality.

3
  • 1
    The anti-pattern begins long before any of the suggested methods. The real anti-pattern is that the base class cares which derived class it is.
    – Dunk
    Commented May 22, 2015 at 19:11
  • The real antipattern is that due to it being 'JavaScript' ,the OP doesn't want to embed the right stuff in the right derived class. If the derived class specifies how it should appear, then that code should be in there. My best suggestion is that you segment and compartmentalize the JavaScript, such that blocks of Javascript can be referred to by Commands. Then in each derived class, you can say "JAVA1HEAD; JAVABODY, JAVABLAHBLAH" in a derived class override. Commented May 22, 2015 at 23:46
  • Or ever better (more fundamentally screwed up) why don't you create a JavaScript function that takes as input the "this.ToString()" className of the Derived class, does a switch on it, and then generates the appropriate code. Commented May 22, 2015 at 23:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.