1

I have class that draw three types of charts, and i want to update it by function public void GetData(PlotModel PlotModel). The main problem is that every series (AreaSeries,CandleStickSeries,HighLowSeries) has different interfaces. How can i update different types in function public void GetData(PlotModel PlotModel). What should i use Activator? Generic?

I think that something like is bad idea:

public void GetData(PlotModel PlotModel) {
    while(true) {
        System.Threading.Thread.Sleep(1000);
        // Add new Item?
        switch(PlotModel.Series.First().ToString()) {
            case "OxyPlot.Series.AreaSeries":
                Console.WriteLine("AreaSeries");
                break;
            case "OxyPlot.Series.CandleStickSeries":
                Console.WriteLine("CandleStickSeries");
                break;
            case "OxyPlot.Series.HighLowSeries":
                Console.WriteLine("HighLowSeries");
                break;
        }
    }
}

Code:

 namespace WpfApplication20 {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            DataContext = new PlotClass();
        }
    }
    public class PlotClass {
        public PlotModel PlotModel { get; set; }
        public PlotClass() {
            PlotModel = new PlotModel();
            DrawCandleChart(PlotModel);
            UpdateChartAsync(PlotModel);
        }
        public void DrawSimpleChart(PlotModel PlotModel) {
            Random rnd = new Random();
            LineSeries LS = new LineSeries();
            for (int i=0;i<10;i++) {
                LS.Points.Add(new DataPoint(i,rnd.NextDouble()));
            }
            PlotModel.Series.Add(LS);
            PlotModel.InvalidatePlot(false);
        }

        public void DrawCandleChart(PlotModel PlotModel) {
            Random rnd = new Random();
            CandleStickSeries CSS = new CandleStickSeries();
            for (int i=0;i<10;i++) {
                CSS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
            }
            PlotModel.Series.Add(CSS);
            PlotModel.InvalidatePlot(false);
        }

        public void DrawHighLowChart(PlotModel PlotModel) {
            Random rnd = new Random();
            HighLowSeries HLS = new HighLowSeries();
            for (int i = 0; i < 10; i++) {
                HLS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
            }
            PlotModel.Series.Add(HLS);
            PlotModel.InvalidatePlot(false);
        }

        public void UpdateChartAsync(PlotModel PlotModel) {
            Action<PlotModel> Update = new Action<PlotModel>(GetData);
            IAsyncResult result = Update.BeginInvoke(PlotModel, null, null);
        }

        public void GetData(PlotModel PlotModel) {
            while(true) {
                System.Threading.Thread.Sleep(1000);
                // Add new Item?
            }
        }
    }
}
4
  • It sounds like your function to update them should belong to the classes themselves. Commented Nov 5, 2015 at 14:38
  • 1
    You should use a timer instead of an infinite while loop. Its not clear though what you mean by add a new item, since your code doesn't really show the different "interfaces" to the plots, its hard to tell you how to make a proxy or adapter to solve the issue. Commented Nov 5, 2015 at 14:44
  • Using dynamic properties can be performance costly. Do you have a base interface in which all models derive from? You could add a Draw method there. Then, as long as your primary method accepts the interface, you call the Draw method on the object. Commented Nov 5, 2015 at 15:32
  • No all models derive from different parents and they do not intersect. Commented Nov 5, 2015 at 15:33

1 Answer 1

3

C# 4 and up offers a nice way of processing situations like this: use cast to dynamic, and call a method with one overload per subtype, like this:

private void Process(AreaSeries arSer) {
    ...
}
private void Process(CandleStickSeries csSer) {
    ...
}
private void Process(HighLowSeries hlSer) {
    ...
}
...
while(true) {
    System.Threading.Thread.Sleep(1000);
    Process((dynamic)PlotModel.Series.First());
    //      ^^^^^^^^^
}

The cast to dynamic makes the "magic" happen: C# will examine the run-time type of PlotModel.Series.First(), and dispatch to one of the three Process methods that you supplied.

There is a danger in this approach: if PlotModel.Series.First() happens to not match any of the overloads, you get a run-time exception. The compiler cannot perform static analysis to tell you that your call would not succeed. Consider adding a catch-all method for the common superclass of your plots, too, so that you could handle unexpected sub-types more gracefully.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.