Home  >  Article  >  Backend Development  >  A simple XML-based module integration framework

A simple XML-based module integration framework

黄舟
黄舟Original
2017-02-28 17:04:051698browse

1. 准备一个xml文件

xmlmenu

 1<Menu>
 2    <MenuItem Name="系统管理" AssemblyName="" FormTag="FALSE" AddToolbar="FALSE">
 3        <MenuItem Name="权限管理" ShortCut="" Image="" AssemblyName="" FormTag="FALSE" AddToolButton="FALSE">
 4            <MenuItem Name="系统权限管理" ShortCut="" Image="passWord.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmSysRight,IntePLM.TyRightWinUI"
  FormTag="TRUE" AddToolButton="FALSE"/>
 5            <MenuItem Name="权限规则定义" ShortCut="" Image="right.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmRightRule,IntePLM.TyRightWinUI" 
 FormTag="TRUE" AddToolButton="FALSE"/>
 6            <MenuItem Name="权限日志" ShortCut="" Image="doc_yellow_edit.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmRightLog,IntePLM.TyRightWinUI"
  FormTag="TRUE" AddToolButton="FALSE"/>
 7        </MenuItem>
8</Menu>

2.准备一个xml schemal文件来验证xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSpy v2006 sp2 U (http://www.altova.com) by peter (hust) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="Menu">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="MenuItem" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="MenuItem">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="MenuItem" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="AddToolButton">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="TRUE"/>
                        <xs:enumeration value="FALSE"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="AddToolbar">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="TRUE"/>
                        <xs:enumeration value="FALSE"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="AssemblyName" type="xs:string" use="required"/>
            <xs:attribute name="FormTag" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="TRUE"/>
                        <xs:enumeration value="FALSE"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="Image" type="xs:string"/>
            <xs:attribute name="Name" type="xs:string" use="required"/>
            <xs:attribute name="ShortCut" use="optional">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:enumeration value="F1"/>
                        <xs:enumeration value="F2"/>
                        <xs:enumeration value="F3"/>
                        <xs:enumeration value="F4"/>
                        <xs:enumeration value="F5"/>
                        <xs:enumeration value="F6"/>
                        <xs:enumeration value="F7"/>
                        <xs:enumeration value="F8"/>
                        <xs:enumeration value="F9"/>
                        <xs:enumeration value="F10"/>
                        <xs:enumeration value="F11"/>
                        <xs:enumeration value="F12"/>
                        <xs:enumeration value="Alt0"/>
                        <xs:enumeration value="Alt1"/>
                        <xs:enumeration value="Alt2"/>
                        <xs:enumeration value="Alt3"/>
                        <xs:enumeration value="Alt4"/>
                        <xs:enumeration value="Alt5"/>
                        <xs:enumeration value="Alt6"/>
                        <xs:enumeration value="Alt7"/>
                        <xs:enumeration value="Alt8"/>
                        <xs:enumeration value="Alt9"/>
                        <xs:enumeration value="AltBksp"/>
                        <xs:enumeration value="AltF1"/>
                        <xs:enumeration value="AltF2"/>
                        <xs:enumeration value="AltF3"/>
                        <xs:enumeration value="AltF4"/>
                        <xs:enumeration value="AltF5"/>
                        <xs:enumeration value="AltF6"/>
                        <xs:enumeration value="AltF7"/>
                        <xs:enumeration value="AltF8"/>
                        <xs:enumeration value="AltF9"/>
                        <xs:enumeration value="AltF10"/>
                        <xs:enumeration value="AltF11"/>
                        <xs:enumeration value="AltF12"/>
                        <xs:enumeration value="AltDownArrow"/>
                        <xs:enumeration value="AltUpArrow"/>
                        <xs:enumeration value="AltLeftArrow"/>
                        <xs:enumeration value="AltRightArrow"/>
                        <xs:enumeration value="Ctrl0"/>
                        <xs:enumeration value="Ctrl1"/>
                        <xs:enumeration value="Ctrl2"/>
                        <xs:enumeration value="Ctrl3"/>
                        <xs:enumeration value="Ctrl4"/>
                        <xs:enumeration value="Ctrl5"/>
                        <xs:enumeration value="Ctrl6"/>
                        <xs:enumeration value="Ctrl7"/>
                        <xs:enumeration value="Ctrl8"/>
                        <xs:enumeration value="Ctrl9"/>
                        <xs:enumeration value="CtrlA"/>
                        <xs:enumeration value="CtrlB"/>
                        <xs:enumeration value="CtrlC"/>
                        <xs:enumeration value="CtrlD"/>
                        <xs:enumeration value="CtrlE"/>
                        <xs:enumeration value="CtrlF"/>
                        <xs:enumeration value="CtrlG"/>
                        <xs:enumeration value="CtrlH"/>
                        <xs:enumeration value="CtrlI"/>
                        <xs:enumeration value="CtrlJ"/>
                        <xs:enumeration value="CtrlK"/>
                        <xs:enumeration value="CtrlL"/>
                        <xs:enumeration value="CtrlM"/>
                        <xs:enumeration value="CtrlN"/>
                        <xs:enumeration value="CtrlO"/>
                        <xs:enumeration value="CtrlP"/>
                        <xs:enumeration value="CtrlQ"/>
                        <xs:enumeration value="CtrlR"/>
                        <xs:enumeration value="CtrlS"/>
                        <xs:enumeration value="CtrlT"/>
                        <xs:enumeration value="CtrlU"/>
                        <xs:enumeration value="CtrlV"/>
                        <xs:enumeration value="CtrlX"/>
                        <xs:enumeration value="CtrlY"/>
                        <xs:enumeration value="CtrlZ"/>
                        <xs:enumeration value="CtrlF1"/>
                        <xs:enumeration value="CtrlF2"/>
                        <xs:enumeration value="CtrlF3"/>
                        <xs:enumeration value="CtrlF4"/>
                        <xs:enumeration value="CtrlF5"/>
                        <xs:enumeration value="CtrlF6"/>
                        <xs:enumeration value="CtrlF7"/>
                        <xs:enumeration value="CtrlF8"/>
                        <xs:enumeration value="CtrlF9"/>
                        <xs:enumeration value="CtrlF10"/>
                        <xs:enumeration value="CtrlF11"/>
                        <xs:enumeration value="CtrlF12"/>
                        <xs:enumeration value="CtrlIns"/>
                        <xs:enumeration value="CtrlShift0"/>
                        <xs:enumeration value="CtrlShift1"/>
                        <xs:enumeration value="CtrlShift2"/>
                        <xs:enumeration value="CtrlShift3"/>
                        <xs:enumeration value="CtrlShift4"/>
                        <xs:enumeration value="CtrlShift5"/>
                        <xs:enumeration value="CtrlShift6"/>
                        <xs:enumeration value="CtrlShift7"/>
                        <xs:enumeration value="CtrlShift8"/>
                        <xs:enumeration value="CtrlShift9"/>
                        <xs:enumeration value="CtrlShiftA"/>
                        <xs:enumeration value="CtrlShiftB"/>
                        <xs:enumeration value="CtrlShiftC"/>
                        <xs:enumeration value="CtrlShiftD"/>
                        <xs:enumeration value="CtrlShiftE"/>
                        <xs:enumeration value="CtrlShiftF"/>
                        <xs:enumeration value="CtrlShiftG"/>
                        <xs:enumeration value="CtrlShiftH"/>
                        <xs:enumeration value="CtrlShiftI"/>
                        <xs:enumeration value="CtrlShiftJ"/>
                        <xs:enumeration value="CtrlShiftK"/>
                        <xs:enumeration value="CtrlShiftL"/>
                        <xs:enumeration value="CtrlShiftM"/>
                        <xs:enumeration value="CtrlShiftN"/>
                        <xs:enumeration value="CtrlShiftO"/>
                        <xs:enumeration value="CtrlShiftP"/>
                        <xs:enumeration value="CtrlShiftQ"/>
                        <xs:enumeration value="CtrlShiftR"/>
                        <xs:enumeration value="CtrlShiftS"/>
                        <xs:enumeration value="CtrlShiftT"/>
                        <xs:enumeration value="CtrlShiftU"/>
                        <xs:enumeration value="CtrlShiftV"/>
                        <xs:enumeration value="CtrlShiftW"/>
                        <xs:enumeration value="CtrlShiftX"/>
                        <xs:enumeration value="CtrlShiftY"/>
                        <xs:enumeration value="CtrlShiftZ"/>
                        <xs:enumeration value="ShiftIns"/>
                        <xs:enumeration value="ShiftF1"/>
                        <xs:enumeration value="ShiftF2"/>
                        <xs:enumeration value="ShiftF3"/>
                        <xs:enumeration value="ShiftF4"/>
                        <xs:enumeration value="ShiftF5"/>
                        <xs:enumeration value="ShiftF6"/>
                        <xs:enumeration value="ShiftF7"/>
                        <xs:enumeration value="ShiftF8"/>
                        <xs:enumeration value="ShiftF9"/>
                        <xs:enumeration value="ShiftF10"/>
                        <xs:enumeration value="ShiftF11"/>
                        <xs:enumeration value="ShiftF12"/>
                        <xs:enumeration value=""/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
    </xs:element>
</xs:schema>

3。定义一个类来加载菜单

public class MenuLoad
    {
        PRivate PluginCollection m_plugins = null;
        public MenuBar _menbar = new MenuBar();
        public ToolStrip _toolbar = new ToolStrip();
        private OutlookBar bar = new OutlookBar();
        private ImageList imglist = new ImageList();
        private StringBuilder builder = new StringBuilder();
        public MenuLoad()
        {
            bar = _menbar.outlookBar;
        }
        private TabControl tabCtrl;
        public TabControl TabCtrl
        {
            set
            {
                tabCtrl = value;
            }
        }
        private void ValidationEventHandler(object sender, ValidationEventArgs e)
        {
            builder.AppendLine("验证XML文档的时候发生错误:");
            builder.AppendLine("严重级别:" + e.Severity);
            builder.AppendLine("错误信息:" + e.Message);
            builder.AppendLine("------+--------+-------+------+--------+-------+------+--------+-------+");
            builder.AppendLine();
        }
        /**//// <summary>
        /// 验证XML文件是否是合乎规范的文件
        /// </summary>
        /// <param name="xmlfile">文件名称</param>
        /// <returns>是则返回true,否则返回false</returns>
        private bool ValidateXml(string xmlfile)
        {
            bool validXml = false;
            string spath = "";
            spath = application.StartupPath + "\\configurations\\XMLSMenu.xsd";
            if(!System.IO.File.Exists(spath))
            {
                throw new System.IO.FileNotFoundException(String.Format(Resources.StringFileNotFound, spath));
            }
            XmlReaderSettings settings = new XmlReaderSettings();
            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.Add(null, spath);
            settings.Schemas.Add(schemaSet);
            settings.ValidationType = ValidationType.Schema;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
            settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;
            XmlReader reader = XmlReader.Create(xmlfile, settings);

            while(reader.Read())
            {
            }
            
            if(builder.Length > 0)
            {
                validXml = false;
            }
            else
            {
                validXml = true;
            }
            reader.Close();
            return validXml;
        }
        /**//// <summary>
        /// 加载菜单
        /// </summary>
        /// <param name="main">主菜单</param>
        /// <param name="xmlfile">菜单定义文件</param>
        public MainMenu LoadMenus(string xmlfile)
        {
            MainMenu mainmenu = new MainMenu();
            
            try
            {
                using(new WaitCursor())
                {
                    //验证XML是否是合乎规范的XML文件
                    if(ValidateXml(xmlfile))
                    {
                        XmlDocument document = new XmlDocument();
                        document.Load(xmlfile);
                        XmlNode rootNode = document.DocumentElement;
                        mainmenu = GetMenus(rootNode);   
                    }
                    else
                    {
                        throw new Exception(builder.ToString());
                    }
                }
            }
            catch (System.IO.FileNotFoundException)
            {
                Utility.ShowErrorMsg(String.Format(Resources.StringFileNotFound, xmlfile));
            }
            return mainmenu;
        }
        /**//// <summary>
        /// 加载菜单
        /// </summary>
        /// <param name="main">主菜单</param>
        /// <param name="node">菜单项节点</param>
        private MainMenu GetMenus(XmlNode node)
        {
            MainMenu mainmenu = new MainMenu();
            List<XmlNode> nodelist= new List<XmlNode>();
            List<OfficeMenuItem> mnulist = new List<OfficeMenuItem>();
            List<IconPanel> iplist = new List<IconPanel>();
            string menutext ="";
            //首先加载主菜单,避免迭代的时候菜单显示的过分延迟。
            foreach(XmlNode child in node.ChildNodes)
            {
                if(child.NodeType == XmlNodeType.Element && child.Name == "MenuItem")
                {
                    menutext = child.Attributes["Name"].Value;
                    OfficeMenuItem item = new OfficeMenuItem(true,menutext);
                    mainmenu.MenuItems.Add(item);
                    IconPanel cp = new IconPanel();
                    bar.AddBand(menutext, cp);
                    nodelist.Add(child);
                    mnulist.Add(item);
                    iplist.Add(cp);
                }
            }
            //加载所有的子菜单
            GetSubMenus(iplist.ToArray(),mnulist.ToArray(), nodelist.ToArray());
            return mainmenu;
        }
        /**//// <summary>
        /// 加载所有子菜单
        /// </summary>
        /// <param name="main">主菜单集合</param>
        /// <param name="node">菜单节点集合</param>
        private void GetSubMenus(IconPanel[] iplist ,OfficeMenuItem[] main, XmlNode[] node)
        {
            EventHandler handler = new EventHandler(OnPluginClick);
            EventHandler handler1 = new EventHandler(OnIconClick);
            EventHandler handler2 = new EventHandler(OnButtonClick);
            string asmname;
            string formtag;
            string text;
            MenuClass mc;
            XmlNode child;
            string iconpath = "";
            string iconname = "";
            string msc = "";
            for(int i = 0; i <= main.GetUpperBound(0); i++)
            {
                //foreach(XmlNode child in node[i].ChildNodes)
                for(int j = 0; j < node[i].ChildNodes.Count;j++ )
                {
                    child = node[i].ChildNodes[j];
                    if(child.NodeType == XmlNodeType.Element && child.Name == "MenuItem")
                    {
                        asmname = child.Attributes["AssemblyName"].Value;
                        formtag = child.Attributes["FormTag"].Value;
                        text = child.Attributes["Name"].Value;
                        msc = child.Attributes["ShortCut"].Value;
                        OfficeMenuItem item = new OfficeMenuItem(true, text, handler);
                        iconname = child.Attributes["Image"].Value;
                        if(iconname != string.Empty)
                        {
                            iconpath = Themes.GetCurrentThemePath() +iconname;
                            item.IconPath = iconpath;
                            
                        } 
                        mc = new MenuClass();
                        mc.Assemblyname = asmname;
                        mc.FormTag = formtag;
                        item.Tag = mc;
                        if(msc != string.Empty)
                        {
                            item.Shortcut = MenuShortCut.GetShortCut(msc);
                        }
                        main[i].MenuItems.Add(item);
                        if((iconpath != string.Empty) && System.IO.File.Exists(iconpath))
                        {    //添加按钮到OutlookBar                        
                            PanelIcon picon = iplist[i].AddIcon(item.Text,Image.FromFile(iconpath),handler1);
                            picon.Tag = mc;
                            //添加按钮到toolbar
                            ToolStripButton button = new ToolStripButton(item.Text, Image.FromFile(iconpath), handler2);
                            button.DisplayStyle = ToolStripItemDisplayStyle.Image;
                            button.ToolTipText = item.Text;
                            button.Tag = mc;
                            button.Visible = true;
                            _toolbar.Items.Add(button);
                        }
                        iconpath = "";
                        mc = null;
                        if(child.ChildNodes.Count > 0)
                        {
                            GetChildMenu(iplist[i],item, child);
                        }
                    }
                }
                //添加分割线
                ToolStripSeparator ss = new ToolStripSeparator();
                _toolbar.Items.Add(ss);
            }
        }
        /**//// <summary>
        /// 加载子菜单
        /// </summary>
        /// <param name="parent">父菜单</param>
        /// <param name="node">父菜单定义XML节点</param>
        private void GetChildMenu(IconPanel ip,OfficeMenuItem parent, XmlNode node)
        {
            EventHandler handler = new EventHandler(OnPluginClick);
            EventHandler handler1 = new EventHandler(OnIconClick);
            EventHandler handler2 = new EventHandler(OnButtonClick);
            MenuClass mc;
            string asmname;
            string formtag;
            string text;
            XmlNode child1;
            string iconpath = "";
            string iconname = "";
            string msc = "";
            //foreach(XmlNode child1 in node.ChildNodes)
            for(int i = 0; i < node.ChildNodes.Count - 1;i++ )
            {
                child1 = node.ChildNodes[i];
                //检查是否提供了类型
                asmname = child1.Attributes["AssemblyName"].Value;
                formtag = child1.Attributes["FormTag"].Value;
                text = child1.Attributes["Name"].Value;
                OfficeMenuItem childitem;
                childitem = new OfficeMenuItem(true, text, handler);
                childitem.Name = text;
                mc = new MenuClass();
                mc.Assemblyname = asmname;
                mc.FormTag = formtag;
                
                childitem.Tag = mc;
                //添加快捷键
                msc = child1.Attributes["ShortCut"].Value;
                if(msc != string.Empty)
                {
                    childitem.Shortcut = MenuShortCut.GetShortCut(msc);
                }
                //添加图标
                iconname = child1.Attributes["Image"].Value;
                if(iconname != string.Empty)
                {
                    iconpath = Themes.GetCurrentThemePath() + iconname;
                    childitem.IconPath = iconpath;
                }
                parent.MenuItems.Add(childitem);
                if((iconpath != string.Empty) && System.IO.File.Exists(iconpath))
                {    //添加按钮到OutlookBar                        
                    PanelIcon picon = ip.AddIcon(childitem.Text, Image.FromFile(iconpath), handler1);
                    picon.Tag = mc;
                    //添加按钮到toolbar
                    ToolStripButton button = new ToolStripButton(childitem.Text, Image.FromFile(iconpath), handler2);
                    button.DisplayStyle = ToolStripItemDisplayStyle.Image;
                    button.ToolTipText = childitem.Text;
                    button.Tag = mc;
                    button.Visible = true;
                    _toolbar.Items.Add(button);
                }
                iconpath = "";
                mc = null;
                if(child1.ChildNodes.Count > 0)
                {
                    GetChildMenu(ip,childitem, child1);
                }
            }
        }
        /**//// <summary>
        /// 打开一个窗体
        /// </summary>
        /// <param name="asmname">窗体类程序集和窗体类的组合,从节点的AssemblyName属性获取</param>
        private  void OpenForm(MenuClass mc)
        {
            string asmname = mc.Assemblyname;
            string formtag = mc.FormTag;
            if (formtag == "")
            {
                throw new Exception(Resources.StringNoFormFlag);
            }
            if(formtag.ToUpper() == "TRUE")
            {
                if(asmname == string.Empty)
                {
                    throw new NullReferenceException(Resources.StringAssemblyNull);
                }

                //string[] a = asmname.Split(&#39;,&#39;);
                object obj = null;
                Type tp = Type.GetType(asmname);
                if(tp != null)
                {
                    obj = Activator.CreateInstance(tp);
                }
                else
                {
                    throw new Exception("加载程序的时候出错,请检查程序(dll,exe)是否存在或者类型是否正确。");
                }

                //检查是否是Form类
                if((obj == null) | !(obj is Form))
                {
                    throw new Exception(Resources.StringNotForm);
                }
                Form frm = (obj as Form);
                //检查打开的第一个窗口是否是MDIFORM
                if(Application.OpenForms[0].IsMdiContainer)
                {
                    //作为MDICHILDFORM
                    frm.MdiParent = Application.OpenForms[0];
                }
                //加载窗体
                frm.Show();

            }
        }
        /**//// <summary>
        /// 菜单单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnPluginClick(object sender, EventArgs args)
        {
            OfficeMenuItem item = (OfficeMenuItem)sender;
            MenuClass mc = (MenuClass) item.Tag;
            if ((item.Text == "退出") | (item.Text == "EXIT"))
            {
                OnExitClick(sender, args);
                return;
            }
            OpenForm(mc);
        }
    }

这里面用到了delegate,最重要的函数是加载菜单的函数和OnPluginClick函数。

使用这个框架可以动态增加任意的层次的模块。

微软的CAB 使用Resigster site方式来增加模块,感觉不是很方便。

 以上就是一个简单的基于XML的模块集成框架的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn