.NET

C#反射与特性应用实例

2020-02-16  本文已影响0人  白龙马5217

应用场景:1用SQL语句从数据库返回一个DataTable对象,2然后绑定到DataGridView控件上,DataGridView列头显示的是数据库里的英文字段名,3要显示中文,需要建个对应的EM实体模型,并设置DisplayName特性;4DataGridView的某一行数据赋值给EM实体实例;5EM实体实例绑定到PropertyGrid控件上;6在PropertyGrid上进行增删改查的操作是很方便的。

1窗口布局

新建一个WinForm项目:ReflectionAndAttribute;摆放一个SplitContainer,Dock=Fill;左边放一个DataGridView:dgv,Dock=Fill;右边放一个PropertyGrid:pg,Dock = Fill;创建好后布局大概如下图:


反射与特性窗口布局

2绑定DataGridView:dgv

-窗口创建Load事件,代码如下:

 private void Form1_Load(object sender, System.EventArgs e)
        {
            OracleDML.ConnectionString = "Data Source=CQYH;User Id=nmis;password=nmis";
            DataTable dt = OracleDML.AllTables();
            dgv.DataSource = dt;
        }

-其中OracleDML.AllTables()代码如下:

/// <summary>
        /// 数据库的全部表
        /// </summary>
        /// <returns></returns>
        public static DataTable AllTables()
        {
            string sql_tables = @"select TABLE_NAME,COMMENTS ,TABLE_TYPE
                            from user_tab_comments
                            where table_type = 'TABLE'
                            order by table_name";
            DataTable allTables = OracleDML.GetDataTable(sql_tables);
            allTables.TableName = "allTables";
            return allTables;
        }

-其中OracleDML.GetDataTable()代码如下:

/// <summary>
        /// 查询SQL_select,返回一个DataTable , 200207 add by Sufuq 
        /// </summary>
        /// <param name="cmdText"></param>
        /// <returns></returns>
        public static DataTable GetDataTable(string SQL_select)
        {
            //OracleCommand cmd = new OracleCommand();

            using (OracleConnection connection = new OracleConnection(ConnectionString))
            {
                OracleDataAdapter ada = new OracleDataAdapter(SQL_select, connection);
                //OracleCommandBuilder ocb = new OracleCommandBuilder(ada); //更新时需要这个
                DataTable dt = new DataTable();
                ada.Fill(dt);
                return dt;
            }
        }

-绑定后的运行效果

直接绑定后列名和SQL语句的名称是一样的英文

3创建EM实体类AllTables

创建换一个EM实体类,并加上[DisplayName()]特性

using System.ComponentModel;

namespace ReflectionAndAttribute
{
    class AllTables
    {
        [DisplayName("表名")]
        public string TABLE_NAME { get; set; }
        [DisplayName("中文名")]
        public string COMMENTS { get; set; }
        [DisplayName("类型")]
        public string TABLE_TYPE { get; set; }
    }
}

4重点来了列头变中文名

-Form1_Load添加如下一样代码:

//列头设置为中文
            AttributeHelper.SetColumnDisplayName(typeof(AllTables), dgv);

-其中SetColumnDisplayName()用到反射和特性

/// <summary>
        /// 根据DataGridView绑定数据源的列名获取EM实体模型的显示名,用来设置列标题。
        /// </summary>
        /// <param name="em"></param>
        /// <param name="dgv"></param>
        public static void SetColumnDisplayName(Type em , DataGridView dgv)
        {
            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                string colName = dgv.Columns[i].Name;
                string DisName = GetDisplayName(em, colName);
                dgv.Columns[i].HeaderCell.Value = DisName;
            } 
        }

        /// <summary>
        /// 获取类的DisplayName显示名
        /// </summary>
        /// <param name="modelType">类名</param>
        /// <param name="propertyDisplayName">类属性名</param>
        /// <returns></returns>
        public static string GetDisplayName(Type modelType, string propertyDisplayName)        
        {
            DisplayNameAttribute dna = TypeDescriptor.GetProperties(modelType)[propertyDisplayName].Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute ;
            string displayName = "";
            if (dna == null)
            {
                displayName = propertyDisplayName;
            }
            else
            {
                displayName = dna.DisplayName;
            }
            return displayName;
            //return (TypeDescriptor.GetProperties(modelType)[propertyDisplayName].Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute).DisplayName;        
        } 
看到没真变中文名显示了

5DataGridView某行数据实例化allTables并绑定PropertyGrid

-Form1上dgv添加RowEnter事件

private void dgv_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
            {
                int row = e.RowIndex;
                //DataGridview行数据实例化AllTables
                AllTables em = AttributeHelper.DgvRowBindTOEM(dgv, row, typeof(AllTables)) as AllTables;
                //绑定到PropertyGrid
                pg.SelectedObject = em;
            }
        }

-其中DgvRowBindTOEM用到反射和特性

 /// <summary>
        /// DataGridView的某行绑定到实体模型EM 
        /// </summary>
        /// <param name="dgv"></param>
        /// <param name="row"></param>
        /// <param name="em"></param>
        /// <returns></returns>
        public static object DgvRowBindTOEM(DataGridView dgv ,int row,Type tEM)
        {
            //根据类型实例化一个对象
            object emReturn = System.Activator.CreateInstance(tEM);
            //dgv的一行数据复制给实体模型对象
            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                string colName = dgv.Columns[i].Name.ToLower(); //数据库名 = 列名.ToLower = 属性名

                //string pName = StringHelper.FirstUpper(colName);//这里还可以加列名转属性名 
                
                PropertyInfo pInfo = tEM.GetProperty(colName); //根据列名取属性信息
                object value = dgv.Rows[row].Cells[colName].Value; //列的数据值
                if (value == System.DBNull.Value) value = value.ToString(); //数据库null转换为string
                pInfo.SetValue(emReturn,value,null); //赋值给实例对象colName属性
            }          
            return emReturn;
        }    

-最终完成效果

看到没就是这么神奇

6对数据的增删改查

6.1查询, DataGridView的查询过滤参阅https://www.jianshu.com/p/b3d6ff3c93d6

6.2新增,只要把绑定在PropertyGrid的类清空即可

比如这样:

AllTables em = new AllTables();
pG.SelectedObject = em;

6.3删除,只要把PropertyGrid绑定的类传给数据访问层操作即可

 AllTables em = (AllTables )pG.SelectedObject;
OracleDML.Delete(em);

6.4修改,只要把PropertyGrid绑定的类传给数据访问层操作即可

 AllTables em = (AllTables )pG.SelectedObject;
OracleDML.Update(em);

。。。。。。。。到此结束。。。。。。。。。。。。

==========我是有底线的===============

上一篇 下一篇

猜你喜欢

热点阅读