本文系原创,转载请注明出处:

https://blog.csdn.net/chengbao315/article/details/82874729

在之前分享的博客中,我已经实现了一个静态加载的小框架,这个框架的模块已经在代码中确定,一旦生成程序,模块将无法改变。但在实际应用的大型项目中,我们更倾向于使用动态加载模块的框架,这样对于项目的移植更加灵活和方便,因此今天我就来实现这个效果,和大家一起分享。先看结果展示:

C#框架编程动态加载模块(一)-LMLPHP

大家看这个动图是不是有种眼花缭乱的赶脚,没办法,CSDN只让上传5M的图片。这次的案例会用到数据库设计、数据库编程、动图加载控件、反射、系统ListView控件等等知识,实现比较复杂,所以我打算分两部分来分享这个小框架的实现过程。

一、数据库设计

因为项目比较简单,并且为了便于使用,本案例中我使用了SQLite数据库。在写代码之前大家需要自行下载 System.Data.SQLite.dll 动态库和 sqlitestudio 数据库管理软件,这里就不做介绍了,如果找不到资源,可以给我留言。

数据库的设计也比较简单,我只添加了几个必要字段,主键、模块名称、动态库路径、类名称、使能、排序、时间戳、图标,如图所示:

C#框架编程动态加载模块(一)-LMLPHP

以上设计就可以满足我要实现的功能了,如有需要,大家可以自行扩展。接下来需要准备DBHelper.cs,网上版本也是一大堆,我这里贴出一版供参考,看代码:

  public class SQLiteHelper
    {
        private static string dbFile = "myFrame.db";

        //生成连接字符串
        private static string CreateConnectionString()
        {
            SQLiteConnectionStringBuilder connectionString = new SQLiteConnectionStringBuilder();
            connectionString.DataSource = @"Data/" + dbFile;

            string conStr = connectionString.ToString();
            return conStr;
        }

        /// <summary>
        /// 对插入到数据库中的空值进行处理
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static object ToDbValue(object value)
        {
            if (value == null)
            {
                return DBNull.Value;
            }
            else
            {
                return value;
            }
        }

        /// <summary>
        /// 对从数据库中读取的空值进行处理
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static object FromDbValue(object value)
        {
            if (value == DBNull.Value)
            {
                return null;
            }
            else
            {
                return value;
            }
        }

        /// <summary>
        /// 执行非查询的数据库操作
        /// </summary>
        /// <param name="sqlString">要执行的sql语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>返回受影响的条数</returns>
        public static int ExecuteNonQuery(string sqlString, params SQLiteParameter[] parameters)
        {
            string connectionString = CreateConnectionString();
            using (SQLiteConnection conn = new SQLiteConnection(connectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sqlString;
                    foreach (SQLiteParameter parameter in parameters)
                    {
                        cmd.Parameters.Add(parameter);
                    }
                    return cmd.ExecuteNonQuery();
                }
            }
        }

        /// <summary>
        /// 执行查询并返回查询结果第一行第一列
        /// </summary>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="sqlparams">参数列表</param>
        /// <returns></returns>
        public static object ExecuteScalar(string sqlString, params SQLiteParameter[] parameters)
        {
            string connectionString = CreateConnectionString();
            using (SQLiteConnection conn = new SQLiteConnection(connectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sqlString;
                    foreach (SQLiteParameter parameter in parameters)
                    {
                        cmd.Parameters.Add(parameter);
                    }
                    return cmd.ExecuteScalar();
                }
            }
        }

        /// <summary>
        /// 查询多条数据
        /// </summary>
        /// <param name="sqlString">SQL语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>返回查询的数据表</returns>
        public static DataTable GetDataTable(string sqlString, params SQLiteParameter[] parameters)
        {
            string connectionString = CreateConnectionString();
            using (SQLiteConnection conn = new SQLiteConnection(connectionString))
            {
                conn.Open();
                using (SQLiteCommand cmd = conn.CreateCommand())
                {
                    cmd.CommandText = sqlString;
                    foreach (SQLiteParameter parameter in parameters)
                    {
                        cmd.Parameters.Add(parameter);
                    }
                    DataSet ds = new DataSet();
                    SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd);
                    adapter.Fill(ds);
                    return ds.Tables[0];
                }
            }
        }
    }

好了,以上我们的数据库准备就基本OK了,下面看模块动态库的准备。

二、准备加载模块

看过前两期文章的朋友应该知道,我之前的模块是与主程序放在一个项目中的,但实际应用中通常模块是分开的,这里我需要新建一个动态库项目,将之前的代码文件添加进去即可。没有做过之前项目的朋友也一样,在新建的动态库项目中新建几个模块界面即可。

C#框架编程动态加载模块(一)-LMLPHP

如图所示,ModuleLib 就是我的模块动态库项目,里面添加了3个模块,大家根据自己需要设计。

三、设计配置页

先来看设计效果吧:

C#框架编程动态加载模块(一)-LMLPHP

界面设计也非常简单一个显示的Table,三个增、删、改按钮和两个确认、取消按钮就OK了,关于这个Table,有很多第三方的控件可以支持,我用过的有FarPoint、Dev GridControl等等,非常方便,大家也可以自行设计。这里为了简单实现,尽量不要其他工具,我使用了系统自带的 ListView 控件。

使用 ListView 控件需要配置以下几个属性:

1. Columns(表头)

C#框架编程动态加载模块(一)-LMLPHP

2. View (设置成Details样式)

C#框架编程动态加载模块(一)-LMLPHP

3. GridLines(表格线)

C#框架编程动态加载模块(一)-LMLPHP

设置完这些,我们的界面设计就基本OK了,其他按钮添加背景图片和文字就可以了。在这个配置页点击新增和编辑按钮都会弹出一个编辑页,下面需要设计一下这个界面。

四、设计编辑页

先看效果图:

C#框架编程动态加载模块(一)-LMLPHP

这个界面就更简单了,只需要几个文本框、下拉框、按钮即可,这里就不做讲解了。强调一下就是下拉框的 DropDownStyle 属性要设置成 DropDownList,不允许编辑的状态。

C#框架编程动态加载模块(一)-LMLPHP

以上就完成了所有的界面设计,下一篇我会分享代码实现过程,欢迎继续关注。

最后,给大家分享一下我的公众号,在里面会发一些技术文章以及博客的更新推送,欢迎大家关注,再次感谢大家的支持!

                                                                

C#框架编程动态加载模块(一)-LMLPHP

                                                                                 扫描二维码,关注我的微信公众号

10-05 08:40