c#泛型和反射的设计应用
文章录入:浣花溪 责任编辑:snow 122
【字体:小 大】
From 心灵魔术师's blog
在设备操作面板的设计中总会有一类固定的按钮和操作惯例,但如果每做一个项目都写一套同样的代码实在很没效率的事。
设备的操作按钮大多数都会包含启动、暂停、停止这三个按钮,软件界面中也同样需要这三类按钮,软件需要根据设备的状态
来禁用或启用不同的按钮组合。比如刚启动软件时,启动按钮开启,暂停和停止按钮禁用等等。
一般设计情况下是用Button,也有的设计会用ToolStripButton,为了使其兼容更多的控件,所以采用了泛型。代码如下:
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);
}
}
}
调用示例:
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++
的一些泛型做法受到限制。
那还有没有更好的方法来达到理想的效果呢,答案是有的,就是反射。看下面改进的代码例子:
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属性即可。
摘自红色黑客联盟(www.7747.net) 原文:http://www.7747.net/kf/201002/44832.html
联系客服