DynamicCreateMenu (反射调用Form)

//创建主菜单 
private void CreateMenus() 
        { 
            MenuStrip mainMenu = new MenuStrip(); 
            DataSet ds = new DataSet(); 
string xmlMenuIndo = System.Windows.Forms.Application.StartupPath;//应用程序运行路径Debug下 
            ds.ReadXml(xmlMenuIndo + @"\sy_menu_wds.xml"); 
            DataView dv = ds.Tables[0].DefaultView; 
            dv.RowFilter = "ParentID=-1"; 
for (int i = 0; i < dv.Count; i++) 
            { 
                ToolStripMenuItem subMenuItem = new ToolStripMenuItem(); 
                subMenuItem.Text = dv[i]["title"].ToString(); 
if (Convert.ToInt16(dv[i]["IsChild"]) == 1) 
                { 
//以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。 
                    CreateSubMenuItem(ref subMenuItem, Convert.ToInt32(dv[i]["ID"]), ds.Tables[0]); 
                } 
                mainMenu.MdiWindowListItem = subMenuItem; 
                mainMenu.Items.Add(subMenuItem); 
            } 
            mainMenu.Dock = DockStyle.Top; 
this.MainMenuStrip = mainMenu; //将窗体的MainMenuStrip梆定为mainMenu. 
this.Controls.Add(mainMenu);   
        } 
//创建子菜单 
private void CreateSubMenuItem(ref ToolStripMenuItem subMenuItem, int ID, DataTable dt) 
        { 
            DataView dv = new DataView(dt); 
            dv.RowFilter = "ParentID="+ID.ToString().Trim(); 
for (int i = 0; i < dv.Count; i++) 
            { 
                ToolStripMenuItem sMenuItem=new ToolStripMenuItem(); 
                sMenuItem.Text = dv[i]["Title"].ToString(); 
if (Convert.ToInt16(dv[i]["IsChild"]) == 1) 
                { 
                    CreateSubMenuItem(ref sMenuItem, Convert.ToInt32(dv[i]["ID"]), dt); 
                } 
else if ("数据备份".Equals(dv[i]["Title"].ToString())) 
                { 
                    sMenuItem.Tag = "BACKUP"; 
                    sMenuItem.Click+=new EventHandler(OtherTools_Click); 
                } 
else if ("退出系统".Equals(dv[i]["Title"].ToString())) 
                { 
                    sMenuItem.Click += new EventHandler(ExitMenuItem_Click); 
                } 
else //没有子菜单,则创建窗体实例 
                { 
                    sMenuItem.Tag = dv[i]["FrmName"].ToString(); 
                    sMenuItem.Click += new EventHandler(sMenuItem_Click); 
                } 
                subMenuItem.DropDownItems.Add(sMenuItem); //将菜单加到顶层菜单下 
            } 
        } 
////菜单单击事件 
void sMenuItem_Click(object sender, EventArgs e) 
        { 
string frmName = ((ToolStripMenuItem)sender).Tag.ToString(); 
            CreateFormInstance(frmName);//创建显示窗体 
        } 
////创建form实例以显示窗体 
private void CreateFormInstance(string formName) 
        { 
bool blflag = false; 
for (int i = 0; i < this.MdiChildren.Length; i++) //若窗体已经打开,则重新激活并打开 
            { 
if (this.MdiChildren[i].Tag.ToString().ToLower() == formName.ToLower()) 
                { 
this.MdiChildren[i].Activate(); 
this.MdiChildren[i].Show(); 
this.MdiChildren[i].WindowState = FormWindowState.Normal; 
                    blflag = true; 
break; 
                } 
            } 
if (!blflag) 
            { 
//利用反射动态生成窗体 
string path = System.Windows.Forms.Application.StartupPath; 
string dllName = formName.Substring(0, formName.IndexOf("."))+".dll"; //得到DLL文件名(Test.dll) 
                Assembly assembly = Assembly.LoadFrom(path + @"\"+dllName+""); 
                Type t = assembly.GetType(formName);//必须是:命名空间.窗体类名(Test.Frm1) 
object obj = Activator.CreateInstance(t); 
                Form frm = (Form)obj; 
                frm.Tag = formName.ToString().Trim();//tag属性要重新写一次,否则在第二次的时候取不到 
                frm.MdiParent = this; 
                frm.Show(); 
            } 
        } 
private void OtherTools_Click(object sender, EventArgs e) 
        { 
switch (((ToolStripMenuItem)(sender)).Tag.ToString().Trim()) 
            { 
case "BACKUP": 
                    { 
                        Tools.DataBack(); 
break; 
                    } 
            } 
        } 
//===========================================// 
//利用.Net自身提供的类对象(例如Form对象、Control对象)利用反射动态创建窗体对象 
//利用反射动态创建窗体对象:事实上就是通过Assembly动态加载DLL 
private void CreateFormInstance(string formName) 
        { 
string str = System.Windows.Forms.Application.StartupPath; 
                Assembly assembly = Assembly.LoadFrom(str+@"\Test.dll"); 
                Type t = assembly.GetType(formName); //formName一定要是[命名空间.窗体名] 
object obj = Activator.CreateInstance(t); 
                Form frm = (Form)obj; 
                frm.MdiParent = this; 
                frm.Show(); 
        } 
//代码说明: 
1)首先是通过Assembly.LoadFrom()来加载dll文件; 
2)再通过GetType()来获得要创建的Form类对象的类型。注意,在GetType()方法的参数为类型的名字,为string类型,同时该名字应为类型的FullName,即:命名空间名.类名; 
3)然后通过Activator.CreateInstance()方法创建该类型对象,返回object对象。 
4)再将该对象强制转换为Form类型。 
5)最后调用即可。 
//结论:对于.Net自身提供的类对象,我们对它直接强制转换即可。不会出现任何问题。 
//===========================================// 
//===========================================// 
//利用自定义对象通过反射动态创建自定义对象(如:窗体对象) 
//动态加载的Dll和手工添加的dll引用,系统会认为不是同一个Assembly。解决方法:应该使用接口 
1、创建一个接口AutoObjectInterface.IAutoObject,该接口包括要加载对象类的方法、属性(AutoObjectInterface.dll) 
2、创建自定义类对象:AutoObject.TestObject(AutoObject.dll) 实现了1中的接口 
3、利用反射动态创建该对象: 
        { 
string str = System.Windows.Forms.Application.StartupPath; 
        Assembly assembly = Assembly.LoadFrom(str+@"\AutoObject.dll"); 
            Type type = assembly.GetType("AutoObject.TestObject"); 
object obj = Activator.CreateInstance(type); 
//因为是自定义对象,所以我们不知道将其转换成什么对象,所以要添加接口的引用,转换的时候就转换为接口的类型了 
            AutoObjectInterface.IAutoObject iObj = (AutoObjectInterface.IAutoObject)obj;  
            iObj.方法(); 
            } 
//这样我们就可以通过接口对象实例来调用类对象的方法 
//结论:在通过反射动态创建对象时,一定要注意区别所创建对象的类型。如果是自定义对象,必须通过单独的接口,来进行类型的转换。 
//===========================================// 
string path = System.Windows.Forms.Application.StartupPath; 
string dllName = formName.Substring(0, formName.IndexOf("."))+".dll"; 
Assembly assembly = Assembly.LoadFrom(path + @"\"+dllName+"");

你可能感兴趣的:(DynamicCreateMenu (反射调用Form))