c#泛型和反射的设计应用(一) 收藏 在设备操作面板的设计中总会有一类固定的按钮和操作惯例,但如果每做一个项目都写一套同样的代码实在很没效率的事。
设备的操作按钮大多数都会包含启动、暂停、停止这三个按钮,软件界面中也同样需要这三类按钮,软件需要根据设备的状态
来禁用或启用不同的按钮组合。比如刚启动软件时,启动按钮开启,暂停和停止按钮禁用等等。
一般设计情况下是用Button,也有的设计会用ToolStripButton,为了使其兼容更多的控件,所以采用了泛型。代码如下:
view plaincopy to clipboardprint? //定义设备状态 public enum OperateState { Run, Pause, Stop }; //设备状态转换规则类 public class OperateStateRule<T> where T : ToolStripItem { private T start; private T pause; private T stop; private OperateState state = OperateState.Stop; private OperateState State { get { return state; } //set { state = value; } } //绑定控件 public OperateStateRule(T _start, T _pause, T _stop) { start = _start; pause = _pause; stop = _stop; Update(OperateState.Stop); } //根据设备状态更新控件属性 public void Update(OperateState _state) { state = _state; try { switch (state) { case OperateState.Stop: start.Enabled = true; pause.Enabled = false; stop.Enabled = false; break; case OperateState.Run: start.Enabled = false; pause.Enabled = true; stop.Enabled = true; break; case OperateState.Pause: start.Enabled = true; pause.Enabled = false; stop.Enabled = true); break; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } //定义设备状态 public enum OperateState { Run, Pause, Stop }; //设备状态转换规则类 public class OperateStateRule<T> where T : ToolStripItem { private T start; private T pause; private T stop; private OperateState state = OperateState.Stop; private OperateState State { get { return state; } //set { state = value; } } //绑定控件 public OperateStateRule(T _start, T _pause, T _stop) { start = _start; pause = _pause; stop = _stop; Update(OperateState.Stop); } //根据设备状态更新控件属性 public void Update(OperateState _state) { state = _state; try { switch (state) { case OperateState.Stop: start.Enabled = true; pause.Enabled = false; stop.Enabled = false; break; case OperateState.Run: start.Enabled = false; pause.Enabled = true; stop.Enabled = true; break; case OperateState.Pause: start.Enabled = true; pause.Enabled = false; stop.Enabled = true); break; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
调用示例:
view plaincopy to clipboardprint? ToolStripButton btnStart; ToolStripButton btnPause; ToolStripButton btnStop; //生成对象时绑定相应的按钮 OperateStateRule<ToolStripButton> rule = new OperateStateRule<ToolStripButton>(btnStart,btnPause,btnStop); //在Click事件里更新状态 private void btnStart_Click(object sender, EventArgs e) { rule.Update(OperateState.Run); } private void btnPause_Click(object sender, EventArgs e) { rule.Update(OperateState.Pause); } private void btnStop_Click(object sender, EventArgs e) { rule.Update(OperateState.Stop); } ToolStripButton btnStart; ToolStripButton btnPause; ToolStripButton btnStop; //生成对象时绑定相应的按钮 OperateStateRule<ToolStripButton> rule = new OperateStateRule<ToolStripButton>(btnStart,btnPause,btnStop); //在Click事件里更新状态 private void btnStart_Click(object sender, EventArgs e) { rule.Update(OperateState.Run); } private void btnPause_Click(object sender, EventArgs e) { rule.Update(OperateState.Pause); } private void btnStop_Click(object sender, EventArgs e) { rule.Update(OperateState.Stop); }
在类声明上有个where T : ToolStripItem语句,这个是c#类型约束,如果不加这个约束,编译器会报错找不到Enabled属性,
但有个问题Button和ToolStripButton这两个类不是同一个基类派生,所以无法兼容使用这2个类,因为必须要有这个约束,使得c++
的一些泛型做法受到限制。
那还有没有更好的方法来达到理想的效果呢,答案是有的,就是反射。看下面改进的代码例子:
view plaincopy to clipboardprint? //枚举设备状态 public enum OperateState { Run, Pause, Stop }; //设备状态转换规则类 public class OperateStateRule<T> { private T start; private T pause; private T stop; private OperateState state = OperateState.Stop; private OperateState State { get { return state; } //set { state = value; } } //绑定控件 public OperateStateRule(T _start, T _pause, T _stop) { start = _start; pause = _pause; stop = _stop; Update(OperateState.Stop); } //通过反射设置属性值 private void SetEnabled(T obj, bool value) { obj.GetType().InvokeMember("Enabled", BindingFlags.SetProperty, null, obj, new object[] { value}); } //根据设备状态更新控件属性 public void Update(OperateState _state) { state = _state; try { switch (state) { case OperateState.Stop: SetEnabled(start, true); SetEnabled(pause, false); SetEnabled(stop, false); break; case OperateState.Run: SetEnabled(start, false); SetEnabled(pause, true); SetEnabled(stop, true); break; case OperateState.Pause: SetEnabled(start, true); SetEnabled(pause, false); SetEnabled(stop, true); break; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } //枚举设备状态 public enum OperateState { Run, Pause, Stop }; //设备状态转换规则类 public class OperateStateRule<T> { private T start; private T pause; private T stop; private OperateState state = OperateState.Stop; private OperateState State { get { return state; } //set { state = value; } } //绑定控件 public OperateStateRule(T _start, T _pause, T _stop) { start = _start; pause = _pause; stop = _stop; Update(OperateState.Stop); } //通过反射设置属性值 private void SetEnabled(T obj, bool value) { obj.GetType().InvokeMember("Enabled", BindingFlags.SetProperty, null, obj, new object[] { value}); } //根据设备状态更新控件属性 public void Update(OperateState _state) { state = _state; try { switch (state) { case OperateState.Stop: SetEnabled(start, true); SetEnabled(pause, false); SetEnabled(stop, false); break; case OperateState.Run: SetEnabled(start, false); SetEnabled(pause, true); SetEnabled(stop, true); break; case OperateState.Pause: SetEnabled(start, true); SetEnabled(pause, false); SetEnabled(stop, true); break; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } }
可以看到已经不需要where子句来约束类型,通过借助泛型和反射实现了更好通用性,不但能使用Button和ToolStripButton,
还能使用其他的控件,只要有Enabled属性即可。
--------------------------------------------------------------------------------
今天突然想到反射可以直接通过Object来直接调用,其实没必要使用泛型,汗~~~~~
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yutao051/archive/2010/02/04/5289025.aspx
|