在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。
1.菜单定义文件可以使用ini或xml格式,这里使用的是xml格式
定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数
dymenu.xml内容如下
<?xml version=1.0?>
<root>
<主菜单>动态菜单1
<子菜单>openform1</子菜单>
<菜单dll>myforms.dll</菜单dll>
<菜单func>openform1</菜单func>
<子菜单>openform2</子菜单>
<菜单dll>myforms.dll</菜单dll>
<菜单func>openform2</菜单func>
</主菜单>
<主菜单>动态菜单2
<子菜单>openform3</子菜单>
<菜单dll>myforms.dll</菜单dll>
<菜单func>openform3</菜单func>
</主菜单>
<主菜单>动态菜单3
<子菜单>openform4</子菜单>
<菜单dll>myforms.dll</菜单dll>
<菜单func>openform4</菜单func>
</主菜单>
</root>
2.菜单对应的myforms.dll
myforms.cs 代码如下:
using system;
namespace myforms
{
public class myforms
{
public myforms()
{
}
public void openform1(system.windows.forms.form mainf)
{
form1 fm = new form1();
fm.mdiparent = mainf;
fm.show();
}
public void openform2(system.windows.forms.form mainf)
{
form2 fm = new form2();
fm.mdiparent = mainf;
fm.show();
}
public void openform3(system.windows.forms.form mainf)
{
form3 fm = new form3();
fm.mdiparent = mainf;
fm.show();
}
public void openform4(system.windows.forms.form mainf)
{
form4 fm = new form4();
fm.mdiparent = mainf;
fm.show();
}
}
}
另外还有4个窗体form1 form2 form3 form4
这里使用的namespace 构造函数 都和dll的名字一致,是为了方便后面主程序调用
3.主程序dymenu.cs
using system;
using system.drawing;
using system.collections;
using system.componentmodel;
using system.windows.forms;
using system.data;
using system.reflection;
using system.xml;
namespace dymenu
{
/// <summary>
/// form1 的摘要说明。
/// </summary>
public class form1 : system.windows.forms.form
{
private system.windows.forms.mainmenu mainmenu1;
//主菜单
private string[] mmenus;
//子菜单
private string[][] mitems;
//子菜单对应的dll
private string[][] mdlls;
//子菜单对应的函数
private string [][] mfuncs;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private system.componentmodel.container components = null;
public form1()
{
//
// windows 窗体设计器支持所必需的
//
initializecomponent();
//
// todo: 在 initializecomponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.dispose();
}
}
base.dispose( disposing );
}
#region windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 – 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void initializecomponent()
{
this.mainmenu1 = new system.windows.forms.mainmenu();
//
//动态生成菜单
//
readxml(); //从菜单定义文件dymenu.xml中读取数据放入定义菜单的数组中
//从数组中取出菜单定义动态生成菜单
for(int i=0;i<mmenus.length;i++)
{
menuitem newdymainitem = new menuitem(mmenus[i]);
this.mainmenu1.menuitems.add(newdymainitem);
for(int j=0;j<mitems[i].length;j++)
{
menuitem newdyitem = new menuitem(mitems[i][j]);
newdymainitem.menuitems.add(newdyitem);
//将每个菜单的click事件指向同一个方法
newdyitem.click += new system.eventhandler(this.newclick);
}
}//end
//这里可以添加一些固定的菜单(不要定义index值,而且一定要在动态生成菜单的后面加,因为后面click事件判断是按index的值来确定的)
this.mainmenu1.menuitems.addrange(new system.windows.forms.menuitem[] {});
//
// form1
//
this.autoscalebasesize = new system.drawing.size(6, 14);
this.clientsize = new system.drawing.size(584, 341);
this.ismdicontainer = true;
this.menu = this.mainmenu1;
this.name = "form1";
this.text = "form1";
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[stathread]
static void main()
{
application.run(new form1());
}
//
//使用反射生成菜单事件
//
private void newclick(object sender, system.eventargs e)
{
menuitem item = (menuitem)sender;
menuitem par = (menuitem)item.parent;
int i = par.index;
int j = item.index;
string idll = mdlls[i][j];
string iclass = idll.substring(0,idll.indexof("."))
+ "."
+ idll.substring(0,idll.indexof("."));
string ifunc = mfuncs[i][j];
try
{
assembly asm = assembly.loadfrom(idll);
type mytype = asm.gettype(iclass);
methodinfo mi = mytype.getmethod(ifunc);
object obj = activator.createinstance(mytype);
mi.invoke(obj,new object[] {this});
}
catch(exception ex)
{
messagebox.show(ex.message);
}
}//end菜单事件
//
//读取菜单文件dymenu.xml
//
public void readxml()
{
xmldocument doc = new xmldocument();
try
{
doc.load("dymenu.xml");
}
catch(exception e)
{
messagebox.show(e.message);
}
xmlelement root = doc.documentelement;
xmlnodelist nodes = root.selectnodes("主菜单");
mmenus = new string[nodes.count];
mitems = new string[nodes.count][];
mdlls = new string[nodes.count][];
mfuncs = new string[nodes.count][];
int j=0;
foreach(xmlnode node in nodes)
{
mmenus[j] = node.innerxml.substring(0,node.innerxml.indexof("<")).trim();
xmlnodelist ns1 = node.selectnodes("子菜单");
int i=0;
mitems[j] = new string[ns1.count];
foreach(xmlnode n in ns1)
{
mitems[j][i] = n.innerxml.trim();
i++;
}
xmlnodelist ns2 = node.selectnodes("菜单dll");
i=0;
mdlls[j] = new string[ns2.count];
foreach(xmlnode n in ns2)
{
mdlls[j][i] = n.innerxml.trim();
i++;
}
xmlnodelist ns3 = node.selectnodes("菜单func");
i=0;
mfuncs[j] = new string[ns3.count];
foreach(xmlnode n in ns3)
{
mfuncs[j][i] = n.innerxml.trim();
i++;
}
j++;
}
}//end读取
}
}