插件架构实战

插件架构实战

 

日期: 2007-3-12

Copyleft (C) 创世纪

    

本文通过一个简单的例子,展示基于插件的框架设计,时间仓促,错误难免,欢迎指正!

1)   加载插件需要的配置文件类 (序列化为XML文件

using System;

namespace LoadPlugins

{

       /// <summary>

       /// 插件接口

       /// </summary>

       public class Plug

       {

              /// <summary>

              /// 菜单名称

              /// </summary>

              public string[] MenuName;

 

              /// <summary>

              /// 链接库名称

              /// </summary>

              public string[] DllName;

 

              /// <summary>

              /// 所属菜单、次序

              /// </summary>

              public string[] Parent;

 

              /// <summary>

              /// 构造函数名称

              /// </summary>

              public string[] ConstructorName;

       }

}

2)  反序列化XML文件, 获取需要加载的插件对象

using System;

using System.Windows.Forms;

using System.IO;

using sx = System.Xml;

using sr = System.Reflection;

namespace LoadPlugins

{

       /// <summary>

       /// 包含序列化和反序列化、反射的一组重要静态方法

       /// </summary>

       public class Serializer

       {

              /// <summary>

              /// XML中反序化出对象 [ 抽取需要加载的插件对象 ]

              /// </summary>

              public static Plug Deserialize(  )

              {

                     string path = Application.StartupPath + "//configuration//COM.XML";

                     if( !File.Exists( path ) )

                     {

                            return null;

                     }

 

                     Plug a = null;

                     try

                     {

                            sx.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer( typeof( Plug ) );

                            Stream s = File.Open( path, FileMode.Open  );

                           

                            a = xs.Deserialize( s ) as Plug;

 

                            s.Close();

                     }

                     catch( Exception ex )

                     {

                            MessageBox.Show( ex.Message );

                     }

 

                     return a;

              }

 

              /// <summary>

              /// 序列化到XML文档 [ 将需要加载为插件的对象序列化到XML文件 ]

              /// </summary>

              /// <param name="MenuName">菜单名称</param>

              /// <param name="DllName">DLL名称</param>

              /// <param name="Parent">所属菜单、次序</param>

              public static  void Serialize( string[] MenuName, string[] DllName, string[] Parent, string[] ConstructorName )

              {

                     Plug a = new Plug( );

                     a.DllName = DllName;

                     a.MenuName = MenuName;

                     a.Parent = Parent;

                     a.ConstructorName = ConstructorName;

 

                     string path = Application.StartupPath + "//configuration//COM.XML";

                    

                     try

                     {

                            Stream s = File.Create( path );            

                            new sx.Serialization.XmlSerializer( a.GetType() ).Serialize( s, a );

                            s.Close();

                     }

                     catch( Exception ex )

                     {

                            MessageBox.Show( ex.Message );

                     }

              }

 

              /// <summary>

              /// 打开插件

              /// </summary>

              /// <param name="dllName">插件名称</param>

              /// <param name="ConstructorName">构造函数名称</param>

              public static void OpenForm( string dllName, string ConstructorName )

              {

                     string path = Application.StartupPath + @" /plug-ins/" + dllName; //路径

                     try

                     {

                            sr.Assembly ass = sr.Assembly.LoadFrom( path );

                            dllName = dllName.Replace( ".dll", string.Empty );

                            Type t = ass.GetType( dllName + "." + ConstructorName,  false, true ); //获取类型,忽略大小写和加载异常

                            object o = System.Activator.CreateInstance( t ); //创建实例

                            Form f = o as Form; //转换得到实例

                            f.ShowDialog();

                     }

                     catch( Exception e )

                     {

                            MessageBox.Show( e.Message );

                     }

              }

 

              /// <summary>

              /// 根据插件名称添加菜单

              /// </summary>

              /// <param name="mm">主菜单</param>

              /// <param name="dNetMenu1">DNetMenu对象</param>

              /// <param name="a">菜单定义对象</param>

              public static void AddPlugin( Menu mm, YuanFeiSoftware.YuanFeiXPControls.DNetMenu dNetMenu1,  Plug a )

              {

                     int i = a.DllName.Length;

                     if( a == null )

                     {

                            return;

                     }

 

                     for( int m = 0; m < i; m ++ )

                     {

                            MenuItem mi = new MenuItem( );

                            mi.Click += new EventHandler( mi_Click );

                            dNetMenu1.SetMenuIcon( mi, null );

                            dNetMenu1.SetSideBarForeColor( mi, System.Drawing.Color.Cornsilk );

                            dNetMenu1.SetSideBarGradientColorOne( mi, System.Drawing.SystemColors.InactiveCaption );

                            dNetMenu1.SetSideBarGradientColorTwo( mi, System.Drawing.SystemColors.ActiveCaption );

                            dNetMenu1.SetSideBarText( mi, null );

                            mi.Text = a.MenuName[ m ];

                            mm.MenuItems[ int.Parse( a.Parent[ m ].Substring( 0, 1 ) ) ].MenuItems.Add( mi );

                     }

              }

 

              /// <summary>

              /// 处理菜单点击事件

              /// </summary>

              /// <param name="sender">数据</param>

              /// <param name="e">数据</param>

              public static void mi_Click( object sender, System.EventArgs e )

              {

                     Plug a = Deserialize();

                     if( a == null )

                     {

                            return;

                     }

 

                     MenuItem mi = sender as MenuItem;

                     int i = 0;

                     for( ; i < a.MenuName.Length; i ++ )

                     {

                            if( a.MenuName[ i ] == mi.Text )

                            {

                                   string DllName = a.DllName[ i ];

                                   OpenForm( DllName + ".dll", a.ConstructorName[ i ] );

                                   break;

                            }

                     }

              }

       }

}

 

3XML配置文件看起来应该是这个样子:(加载一个菜单名称为“开创世纪”的DLL

<?xml version="1.0"?>

<Plug xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <MenuName>

    <string>开创世纪(&amp;C)</string>

  </MenuName>

  <DllName>

    <string>MyFuture</string>

  </DllName>

  <Parent>

    <string>1-5</string>

  </Parent>

  <ConstructorName>

    <string>Future</string>

  </ConstructorName>

</Plug>

 

4)  在主窗口的构造方法内调用相应方法,完成DLL的加载:

LoadPlugins.Serializer.AddPlugin( this.mainMenu1, this.dNetMenu1, LoadPlugins.Serializer.Deserialize() );

 

如上所述,一个简单的插件系统就这样设计成了,下面测试一下。将需要加载的DLL拷贝到启动目录下的plug-ins目录下,修改配置文件,然后看起来是这个样子。

 

 

 

 

 效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值