前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >模块式开发

模块式开发

作者头像
逸鹏
发布2018-04-11 11:18:19
1K0
发布2018-04-11 11:18:19
举报
文章被收录于专栏:逸鹏说道逸鹏说道逸鹏说道

这两天看到同事的一个小工具,用的是模块式开发,也就是俗称的插件开发,用的是反射+接口的方式实现的。感觉挺好的,也就学习了一下,写个小Demo,在此记录下。

一、写接口类

接口类是所有模块的基础,因为让主程序去寻找模块,就是通过反射来找到继承此接口的相关项目,也就是后期包含继承此接口类的DLL文件。

此接口类包含以下几个属性

工具的名称(必需)、是否要弹出、前景色、背景色、工具启动方法(必需)

public interface IToolsInterface
    {        /// <summary>
        /// 获取工具名称        /// </summary>
        string ToolName
        {            get;
        }        /// <summary>
        /// 是否弹出        /// </summary>
        bool IsPopUp
        {            get;
        }        /// <summary>
        /// 前景色        /// </summary>        Brush ForgroundBrush
        {            get;
        }        /// <summary>
        /// 背景色        /// </summary>        Brush BackgroundBrush
        {            get;
        }        /// <summary>
        /// 工具启动方法        /// </summary>
        /// <returns></returns>        FrameworkElement RunToolApplication();
    }

二、写主窗体

所谓的主窗体,也就是各个模块的承载器而已,因为各个模块都是UserControl,需要窗体来承载。

需要的方法大概有两个,寻找目录的层级、创建相应的模块。

1、寻找目录层级

因为模块最终要生成到一个位置,然后让主程序去搜索,所以,需要一个搜索方法,去寻找

        /// <summary>
        /// 查找指定目录下的所有末级子目录        /// </summary>
        /// <param name="dir">要查找的目录</param>
        /// <param name="dirList">查找结果列表</param>
        /// <param name="system">是否包含系统目录</param>
        /// <param name="hidden">是否包含隐藏目录</param>
        public static void GetEndDirectories(DirectoryInfo dir,List<DirectoryInfo> dirList,bool system=false,bool hidden=false)
        {            try
            {                //返回当前目录的子目录集合
                DirectoryInfo[] dirSub = dir.GetDirectories();                if(dirSub.Length==0)
                {                    //如果没有子目录了则添加进列表                    dirList.Add(dir);                    return;
                }                foreach (DirectoryInfo subItem in dirSub)
                {                    //跳过系统目录
                    if (!system && (subItem.Attributes & FileAttributes.System)==FileAttributes.System)
                    {                        continue;
                    }                    //跳过隐藏目录
                    if (!hidden && (subItem.Attributes & FileAttributes.Hidden)==FileAttributes.Hidden)
                    {                        continue;
                    }                    //递归                    GetEndDirectories(subItem, dirList);
                }
            }            catch (Exception ex)
            {
                MessageBox.Show("获取目录层级失败。" + ex.Message);
            }
        }    

2、创建相应模块

当存在一个DLL时,就生成一个模块,两个DLL时就要有两个模块,以此类推……

     /// <summary>
        /// 创建功能按钮        /// </summary>
        /// <param name="toolsInterface"></param>
        /// <returns></returns>
        private UIElement CreateFunction(IToolsInterface toolsInterface)
        {
            Button btn = new Button();
            btn.Click += Btn_Click;
            btn.Content = toolsInterface.ToolName;
            btn.Width = 100;
            btn.Height = 50;
            btn.Margin = new Thickness(5, 0, 0, 0);
            btn.Background = toolsInterface.BackgroundBrush;
            btn.Foreground = toolsInterface.ForgroundBrush;
            btn.Tag = toolsInterface;            return btn;
        }        private void Btn_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;            if(btn!=null)
            {
                IToolsInterface toolsInterface = btn.Tag as IToolsInterface;                if(toolsInterface !=null)
                {
                    FrameworkElement control = toolsInterface.RunToolApplication();

                    gUc.Children.Clear();
                    gUc.Children.Add(control);
                }                else
                {
                    MessageBox.Show("实例化接口失败");
                }
            }            else
            {
                MessageBox.Show("实例化按钮失败");
            }
        }

3、加载模块

     private void LoadWidgets()
        {            string applicationPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;            string dirPath = applicationPath + "Widgets/";            if(!Directory.Exists(dirPath))
            {
                MessageBox.Show("未找到相关的Widgets文件夹信息,请确认相关的文件夹是否存在。");                return;
            }
            DirectoryInfo dir = new DirectoryInfo(dirPath);
            List<DirectoryInfo> lastDirNameList = new List<DirectoryInfo>();
            Tools.FileToolsHelper.GetEndDirectories(dir, lastDirNameList);            foreach (DirectoryInfo item in lastDirNameList)
            {
                WrapPanel wrapPanel = null;
                TabItem tabItem = Tools.UCToolsHelper.CreateTabByDirName(item.Name,tcToolkClass);
                wrapPanel = Tools.UCToolsHelper.CreateWrapPanel(tabItem);                string[] dllFilesPath = Directory.GetFiles(item.FullName, "*.dll");                foreach (string dllPath in dllFilesPath)
                {
                    Assembly assembly = Assembly.LoadFile(dllPath);
                    Type[] types = assembly.GetExportedTypes();                    foreach (Type type in types)
                    {                        if(typeof(IToolsInterface).IsAssignableFrom(type)&&!type.IsAbstract)
                        {
                            IToolsInterface toolInterface = Activator.CreateInstance(type) as IToolsInterface;                            if (toolInterface !=null)
                            {
                                wrapPanel.Children.Add(CreateFunction(toolInterface));
                            }
                        }
                    }
                }
            }
        }

三、写相应的模块部分

最近也没写什么小东西,就把原来做的两个Winform东西,直接搬过来,弄成了WPF的,把窗体改成了UserControl,额外加了一个类,用来实现第一部分提到的接口。

其中一个小工具在这:http://www.cnblogs.com/ZXdeveloper/p/5682230.html

基本东西不动,只是加了一个FunctionHelper用来实现接口,此处需要注意,一定是Public,否则查询不到

public class FunctionHelper : IToolsInterface
    {        public Brush BackgroundBrush
        {            get
            {                return new SolidColorBrush(Colors.LightBlue);
            }
        }        public Brush ForgroundBrush
        {            get
            {                return new SolidColorBrush(Colors.YellowGreen);
            }
        }        public bool IsPopUp
        {            get
            {                return false;
            }
        }        public string ToolName
        {            get
            {                return "方法查询工具";
            }
        }        public FrameworkElement RunToolApplication()
        {            return new SearchUC();
        }
    }

四、看一下效果图

大概也就这么一个流程,不是很难,方便了后期的开发。

DEMO还有很多不完善的地方,我会慢慢弄,后期会不断的完善

DEMO

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我为Net狂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档