zoukankan      html  css  js  c++  java
  • 小白详细解析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的子类



     
  • 相关阅读:
    什么是 bean 的自动装配?
    什么是 Spring 的内部 bean?
    什么是 Spring 的 MVC 框架?
    Spring AOP and AspectJ AOP 有什么区别?
    解释 JDBC 抽象和 DAO 模块?
    volatile 类型变量提供什么保证?
    一个 Spring Bean 定义 包含什么?
    什么是 Spring MVC 框架的控制器?
    使用 Spring 访问 Hibernate 的方法有哪些?
    什么是 Callable 和 Future?
  • 原文地址:https://www.cnblogs.com/tangtangde12580/p/9497856.html
Copyright © 2011-2022 走看看