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?

  • define a method in the widget that the subclasses implement, e.g. public abstract class Widget { public void Display() } – Caleth May 22 '15 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 May 22 '15 at 13:15
  • well you could expose is as an IWidgetDisplayRepresentation that your Javascript writer consumes – Caleth May 22 '15 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?) – Marjan Venema May 22 '15 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 May 22 '15 at 20:46
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 for the overload approach, but your WidgetToJavaScriptConverter instance could be called from a simple loop without the added indirection of a visitor pattern. – Marjan Venema May 22 '15 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.

  • 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 May 22 '15 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. – Andyz Smith May 22 '15 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. – Andyz Smith May 22 '15 at 23:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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