zoukankan      html  css  js  c++  java
  • 模块式开发

    这两天看到同事的一个小工具,用的是模块式开发,也就是俗称的插件开发,用的是反射+接口的方式实现的。感觉挺好的,也就学习了一下,写个小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

  • 相关阅读:
    SPOJ 694 (后缀数组) Distinct Substrings
    POJ 2774 (后缀数组 最长公共字串) Long Long Message
    POJ 3693 (后缀数组) Maximum repetition substring
    POJ 3261 (后缀数组 二分) Milk Patterns
    UVa 1149 (贪心) Bin Packing
    UVa 12206 (字符串哈希) Stammering Aliens
    UVa 11210 (DFS) Chinese Mahjong
    UVa (BFS) The Monocycle
    UVa 11624 (BFS) Fire!
    HDU 3032 (Nim博弈变形) Nim or not Nim?
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/5959476.html
Copyright © 2011-2022 走看看