创建未知类型的实例
Create instance of unknown type
我有 class 绘制三种类型的图表,我想通过函数 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
的转换使 "magic" 发生:C# 将检查 PlotModel.Series.First()
的 运行 时间类型,并分派给三个 [=] 之一14=] 您提供的方法。
这种方法存在危险:如果 PlotModel.Series.First()
碰巧 不 匹配任何重载,您将得到 运行 次异常。编译器无法执行静态分析来告诉您调用不会成功。也可以考虑为绘图的公共超类添加一个包罗万象的方法,这样您就可以更优雅地处理意外的子类型。
我有 class 绘制三种类型的图表,我想通过函数 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
的转换使 "magic" 发生:C# 将检查 PlotModel.Series.First()
的 运行 时间类型,并分派给三个 [=] 之一14=] 您提供的方法。
这种方法存在危险:如果 PlotModel.Series.First()
碰巧 不 匹配任何重载,您将得到 运行 次异常。编译器无法执行静态分析来告诉您调用不会成功。也可以考虑为绘图的公共超类添加一个包罗万象的方法,这样您就可以更优雅地处理意外的子类型。