• 小白详细解析C#反射特性实例


      套用MSDN上对于反射的定义:反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

    地址:https://msdn.microsoft.com/zh-cn/library/ms173183(VS.80).aspx

      贴上示例代码:

    首先程序入口代码Program

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        static class Program
        {
            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                UserInf userss = new UserInf();
                userss.U_UserID = "aw12311";
                userss.U_Psw = "123";
                userss.U_UserName = "aw";
                userss.U_City = "武汉";
                userss.U_Popedom = 1;
                userss.U_Sex = 1;
                userss.U_BirthTime = 19900114;
                userss.U_AddDataTime = DateTime.Now;
    
                DateIsTableAttribute<UserInf> t = new DateIsTableAttribute<UserInf>();
    
                t.insertDate(userss);
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }

    将要被反射的程序类UserInf

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WindowsFormsApp1
    {
        [Table("Consumers")]
        public class UserInf
        {
            private string _UserID;
            /// <summary>
            /// 登陆ID
            /// </summary>
            [Field("ConsumerID", DbType.String, 12)]
            public string U_UserID
            {
                get { return _UserID; }
                set { _UserID = value; }
            }
    
            private string _Psw;
            /// <summary>
            /// 登陆密码
            /// </summary>
            [Field("ConsumerPwd", DbType.String, 12)]
            public string U_Psw
            {
                get { return _Psw; }
                set { _Psw = value; }
            }
    
            private string _UserName;
            /// <summary>
            /// 用户别称
            /// </summary>
            [Field("ConsumerName", DbType.String, 50)]
            public string U_UserName
            {
                get { return _UserName; }
                set { _UserName = value; }
            }
    
            private string _City;
            /// <summary>
            /// 所住城市
            /// </summary>
            [Field("UserCity", DbType.String, 50)]
            public string U_City
            {
                get { return _City; }
                set { _City = value; }
            }
    
            private int _Popedom;
            /// <summary>
            /// 权限
            /// </summary>
            [Field("popedom", DbType.Int32, 0)]
            public int U_Popedom
            {
                get { return _Popedom; }
                set { _Popedom = value; }
            }
    
            private DateTime _AddDataTime;
            /// <summary>
            /// 注册时间
            /// </summary>
            [Field("addDataTime", DbType.Date, 0)]
            public DateTime U_AddDataTime
            {
                get { return _AddDataTime; }
                set { _AddDataTime = value; }
            }
    
            private int _Sex;
            /// <summary>
            /// 性别
            /// </summary>
            [Field("Sex", DbType.Int32, 0)]
            public int U_Sex
            {
                get { return _Sex; }
                set { _Sex = value; }
            }
    
            private int _BirthTime;
            /// <summary>
            /// 出身日期;
            /// </summary>
            [Field("BirthTime", DbType.String, 9)]
            public int U_BirthTime
            {
                get { return _BirthTime; }
                set { _BirthTime = value; }
            }
        }
    }

    将要被反射的程序类中引伸的自定义特性类:包括预定义特性[AttributeUsage(...)]和自定义特性类具体内容

      1、自定义特性类TableAttribute

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace WindowsFormsApp1
    {
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    
        public class TableAttribute : Attribute
        {
            private string _TableName;
    
            /// <summary>
            /// 映射的表名
            /// </summary>
            public string TableName
            {
                get { return _TableName; }
            }
    
            /// <summary>
            /// 定位函数映射表名;
            /// </summary>
            /// <param name="table"></param>
            public TableAttribute(string table)
            {
                _TableName = table;
            }
        }
    }

      2、自定义特性类FieldAttribute

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WindowsFormsApp1
    {
        [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
        public class FieldAttribute : Attribute
        {
            private string _Fields;
            /// <summary>
            /// 字段名称 keleyi.com
            /// </summary>
            public string Fields
            {
                get { return _Fields; }
            }
    
            private DbType _Dbtype;
            /// <summary>
            /// 字段类型
            /// </summary>
            public DbType Dbtype
            {
                get { return _Dbtype; }
    
            }
    
            private int _ValueLength;
            /// <summary>
            /// 字段值长度
            /// </summary>
            public int ValueLength
            {
                get { return _ValueLength; }
            }
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="fields"> 字段名</param>
            /// <param name="types"> 字段类型</param>
            /// <param name="i"> 字段值长度</param>
            public FieldAttribute(string fields, DbType types, int i)
            {
                _Fields = fields;
                _Dbtype = types;
                _ValueLength = i;
            }
        }
    }

    最后使用Type类型将封装的程序集的类型绑定到现有对象,并利用当前对象访问、检测和修改封装的程序集中特性

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Reflection;
    
    namespace WindowsFormsApp1
    {
        public class DateIsTableAttribute<T>
        {
            public string insertDate(T types)
            {
                string cmdtxt = "insert into ";
                string cmdparVar = null;
                Type userAttu = types.GetType();
                TableAttribute tables = (TableAttribute)userAttu.GetCustomAttributes(false)[0];//UserInf中的Table结点
                cmdtxt += tables.TableName + "(";
                PropertyInfo[] info = userAttu.GetProperties();
                foreach (PropertyInfo prs in info)
                {
                    object[] attu = prs.GetCustomAttributes(false);
                    foreach (Attribute abute in attu)
                    {
                        if (abute is FieldAttribute)
                        {
                            FieldAttribute midle = abute as FieldAttribute;
                            cmdtxt += midle.Fields + ",";
                            object obj = prs.GetGetMethod().Invoke(types, null);
                            if (midle.Dbtype == DbType.Int32)
                                cmdparVar += obj + ",";
                            else
                                cmdparVar += "'" + obj + "',";
                        }
                    }
                }
                cmdparVar = cmdparVar.Substring(0, cmdparVar.Length - 1);
                cmdtxt = cmdtxt.Substring(0, cmdtxt.Length - 1) + ")";return cmdtxt;
            }
        }
    }

    由于我使用窗口程序测试,没有设置测试结果的显示。可以将程序使用控制台实现,将cmdparVar和cmdtxt显示出来。

    断点运行可以看到 

    cmdparVar值:'aw12311','123','aw','武汉',1,'2018/8/18 16:43:17',1,'19900114'
    cmdtxt值:insert into Consumers(ConsumerID,ConsumerPwd,ConsumerName,UserCity,popedom,addDataTime,Sex,BirthTime)
    利用Type类型读取到了传入程序集中的变量值。

    程序结构分析:
    Program为程序入口
    UserInf为将要被反射的类:自定义了一个类属性“
    Table”,Table类属性附加了一个参数。自定义了变量属性“Field”,Field变量属性附加了3个参数。
    自定义特性类TableAttribute:对UserInf的类属性“Table”重新构建并获取自定义附加参数。
    自定义特性类FieldAttribute:对UserInf的变量属性“Field”重新构建并获取自定义附加参数。
    程序过程分析:
    一、入口程序往UserInf的各个变量进行赋值。
    二、将UserInf传入模板类DateIsTableAttribute,模板类DateIsTableAttribute实现用Type反射UserInf属性。

    以下进行DateIsTableAttribute详细解析:
        public class DateIsTableAttribute<T>  //实例化模板类DateIsTableAttribute时,传入T类型
        {
            public string insertDate(T types) //用传入T类型新建types变量
            {
                string cmdtxt = "insert into ";
                string cmdparVar = null;
                Type userAttu = types.GetType(); //获取types的类型(即传入的T类型)的当前实例传给Type类型userAttu,即反射的定义
                TableAttribute tables = (TableAttribute)userAttu.GetCustomAttributes(false)[0];//获取已实例化Type类型userAttu中的直接结点并调用派生自attribute的类TableName(传入为自定义的特性)
            //并强制转换为TableAttribute类型
            //转换成TableAttribute类型是为了更好调用自定义的附加参数,比如下面tables的TableName值。 cmdtxt += tables.TableName + "("; PropertyInfo[] info = userAttu.GetProperties();//获取传入的当前实例中的所有公共属性 foreach (PropertyInfo prs in info)//遍历所有带有attribute公共属性的元数据变量 { object[] attu = prs.GetCustomAttributes(false);//获取此元数据中派生自Attribute类的结点 foreach (Attribute abute in attu)//遍历元数据中的自定义结点 { if (abute is FieldAttribute)//若为Field结点 { FieldAttribute midle = abute as FieldAttribute;//强制转换当前attibute属性 cmdtxt += midle.Fields + ",";//读取属性值 object obj = prs.GetGetMethod().Invoke(types, null); if (midle.Dbtype == DbType.Int32) cmdparVar += obj + ","; else cmdparVar += "'" + obj + "',"; } } } cmdparVar = cmdparVar.Substring(0, cmdparVar.Length - 1); cmdtxt = cmdtxt.Substring(0, cmdtxt.Length - 1) + ")";return cmdtxt; } } }


    用到的几个函数接口:
    types.GetType():获取types当前实例的Type
    Type.GetCustomAttributes(false)[0] :获取Type类型参数第一个自定义特性结点,返回为自定义特性结点的特征值,比如名称、类型、长度等
    Type.GetCustomAttributes(false) 获取Type类型参数所有自定义特性结点,返回为所有自定义特性结点的特征值(比如名称、类型、长度等)组,示例中将返回的自定义特征值强制转换为自定义特性类
    链接:https://msdn.microsoft.com/zh-cn/library/system.type.getcustomattributes.aspx
    TableAttribute或FieldAttribute,可以更方便读取其中的自定义附加参数
    Type.GetProperties() 返回当前Type的所有公共属性
    链接:https://technet.microsoft.com/zh-cn/windowsserver/1zkfcy34
    PropertyInfo.GetGetMethod() 返回此属性公共get访问器
    链接:https://technet.microsoft.com/zh-cn/windowsserver/1zkfcy34
    Method().Invoke(obj, null);反射执行该类型示例方法,obj为方法所属类型实例
    http://blog.sina.com.cn/s/blog_976ba8a501010y5k.html

    延伸:
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    https://blog.csdn.net/honey199396/article/details/51316754

    typeof(Animal).IsAssignFrom(typeof(Dog)) 他返回true的条件是 Dog类直接或间接的实现了Animal类;继承也可以

    typeof(Dog).IsSubClassOf(typeof(Animal)) 他返回true的条件是Dog类是Animal的子类



     
  • 相关阅读:
    排序算法系列之冒泡排序 (3)
    排序算法系列之选择排序 (2)
    排序算法系列之插入排序 (1)
    深挖 NGUI 基础 之UICamera (二)
    深挖 NGUI 基础 之UIRoot (一)
    JPS寻路和AStar寻路
    旋转矩阵
    [斜边的血条进度]
    UI框架:ui节点控件的绑定方式
    Shader播放序列帧
  • 原文地址:https://www.cnblogs.com/tangtangde12580/p/9497856.html
Copyright © 2020-2023  润新知