我有绘制三种类型图表的类,我想通过功能public void GetData(PlotModel PlotModel)更新它。主要问题是每个系列(AreaSeries,CandleStickSeries,HighLowSeries)具有不同的接口。如何更新功能public void GetData(PlotModel PlotModel)中的不同类型。我应该使用什么激活剂?泛型?

我认为这样是个坏主意:

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;
        }
    }
}


码:

 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?
            }
        }
    }
}

最佳答案

C#4及更高版本提供了一种处理此类情况的好方法:使用强制转换为dynamic,并调用每个子类型具有一个重载的方法,如下所示:

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());
    //      ^^^^^^^^^
}


强制转换为dynamic使“魔术”发生:C#将检查PlotModel.Series.First()的运行时类型,并分派给您提供的三个Process方法之一。

这种方法有一个危险:如果PlotModel.Series.First()碰巧与任何重载都不匹配,则会出现运行时异常。编译器无法执行静态分析以告知您调用将不会成功。也考虑为绘图的公共超类添加一个包罗万象的方法,以便您可以更优雅地处理意外的子类型。

09-17 13:55