美文网首页.NET
C#反射与特性应用实例

C#反射与特性应用实例

作者: 白龙马5217 | 来源:发表于2020-02-16 21:08 被阅读0次

应用场景: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);

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

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

相关文章

  • C#反射与特性应用实例

    应用场景:1用SQL语句从数据库返回一个DataTable对象,2然后绑定到DataGridView控件上,Dat...

  • C#它山之石

    C# 使用反射技术实例化指定的类C#之玩转反射Reactive Extensions入门IoC solutions...

  • C#特性(Attribute)-现学现用

    前言 想要灵性的使用C#反射机制,特性(Attribute)的使用是必不可少的。 C# 特性(Attribute)...

  • Unity 之如何写出强壮的代码

    【反射】 Unity C#基础之 反射反射,程序员的快乐 Unity C#基础之 特性,一个灵活的小工具 【多线程...

  • 目录 - C#

    总目录 C# 第01局:泛型 C# 第02局:反射 C# 第03局:特性 C# 第04局:委托 C# 第05局:事...

  • C#之反射与特性篇

    反射 定义 类型 Type:描述程序集,类型等的元数据信息 反射 Reflect:一个运行时获取元数据信息的过程,...

  • reflect.go包学习_之二 指针操作提高反射性能 反射应用

    reflect.go包学习_之二 指针操作提高反射性能 反射应用 反射创建实例 反射信息、反射调用方法、反射修改值...

  • Java高级特性整理

    Java高级特性 反射 使用场景 功能 获取Class对象方式 判断是否为类的实例 创建实例 newInstanc...

  • 利用自定义类特性与反射来解耦

    其实主要是利用类特性,来存储程序集信息,在利用反射创建实例。与将程序集信息写在配置文件里效果一样。首先新建特性类,...

  • 知识点|C#高级知识:Attribute特性

    C#特性[Attribute]是一类特殊的语法结构,我们掌握了特性的相关用法,就能在运行时,通过反射,得到一些额外...

网友评论

    本文标题:C#反射与特性应用实例

    本文链接:https://www.haomeiwen.com/subject/wujmfhtx.html