套用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 = "";
userss.U_UserName = "aw";
userss.U_City = "武汉";
userss.U_Popedom = ;
userss.U_Sex = ;
userss.U_BirthTime = ;
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, )]
public string U_UserID
{
get { return _UserID; }
set { _UserID = value; }
} private string _Psw;
/// <summary>
/// 登陆密码
/// </summary>
[Field("ConsumerPwd", DbType.String, )]
public string U_Psw
{
get { return _Psw; }
set { _Psw = value; }
} private string _UserName;
/// <summary>
/// 用户别称
/// </summary>
[Field("ConsumerName", DbType.String, )]
public string U_UserName
{
get { return _UserName; }
set { _UserName = value; }
} private string _City;
/// <summary>
/// 所住城市
/// </summary>
[Field("UserCity", DbType.String, )]
public string U_City
{
get { return _City; }
set { _City = value; }
} private int _Popedom;
/// <summary>
/// 权限
/// </summary>
[Field("popedom", DbType.Int32, )]
public int U_Popedom
{
get { return _Popedom; }
set { _Popedom = value; }
} private DateTime _AddDataTime;
/// <summary>
/// 注册时间
/// </summary>
[Field("addDataTime", DbType.Date, )]
public DateTime U_AddDataTime
{
get { return _AddDataTime; }
set { _AddDataTime = value; }
} private int _Sex;
/// <summary>
/// 性别
/// </summary>
[Field("Sex", DbType.Int32, )]
public int U_Sex
{
get { return _Sex; }
set { _Sex = value; }
} private int _BirthTime;
/// <summary>
/// 出身日期;
/// </summary>
[Field("BirthTime", DbType.String, )]
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)[];//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(, cmdparVar.Length - );
cmdtxt = cmdtxt.Substring(, cmdtxt.Length - ) + ")";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的子类


 

小白详细解析C#反射特性实例的更多相关文章

  1. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

  2. java类生命周期详细解析

    (一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前 ...

  3. springmvc 项目完整示例06 日志–log4j 参数详细解析 log4j如何配置

    Log4j由三个重要的组件构成: 日志信息的优先级 日志信息的输出目的地 日志信息的输出格式 日志信息的优先级从高到低有ERROR.WARN. INFO.DEBUG,分别用来指定这条日志信息的重要程度 ...

  4. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

  5. 单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式

    单表扫描,MySQL索引选择不正确 并 详细解析OPTIMIZER_TRACE格式     一 表结构如下:  万行 CREATE TABLE t_audit_operate_log (  Fid b ...

  6. python闭包的详细解析

    一.什么是闭包? 如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包 闭包必须满足三个条件: 1. 必须有一个内嵌函数    2. 内嵌函数必须引用外部嵌套函数中的变量  ...

  7. ZT Linux系统环境下的Socket编程详细解析

    Linux系统环境下的Socket编程详细解析 来自: http://blog.163.com/jiangh_1982/blog/static/121950520082881457775/ 什么是So ...

  8. 【转】UML中的几种关系详细解析

    UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统中, ...

  9. 从多谐振荡器详细解析到555定时器基本电路(控制LED闪烁)

    在学期末,笔者参加了学校的电工实习,前六天做都很快,但是今天要做一个关于555多谐振荡器的LED闪烁电路,由于笔者没有提前准备,导致今天就算把电路搭建出来也不懂具体原理,耗费了不少时间,所以我打算专门 ...

随机推荐

  1. 网站配置新的YII2可运行版本

    1. config 中的 gitignore 先将 -local 加入版本库 2. 将 runtime 目录添加写权限 3. 将web目录的asset 添加写的权限 4.

  2. 命令行执行 mvn package 和常见mvn命令

    cmd 打开命令提示符, 然后打开代码所在目录,例如 d: cd d:/code 执行 mvn package Maven常用命令:  1. 创建Maven的普通java项目:     mvn arc ...

  3. SVN客户端--TortoiseSVN使用说明【转】

    TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...

  4. 浅谈对MVC的理解

    1.MVC设计模式理解 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界 ...

  5. 【扫盲贴】为什么屏幕分辨率是 640x480

    本文原地址:http://www.easyx.cn/skills/View.aspx?id=172 常见的屏幕分辨率很奇怪,为什么总用一些不零不整的数字?比如以前最常见的分辨率是 640x480,当初 ...

  6. webapi权限常见错误

    webapi权限常见错误 错误一: Response for preflight has invalid HTTP status code 405. 解决方案: 屏蔽配置文件中的如下代码 <!- ...

  7. BZOJ3638|CodeForces 280D k-Maximum Subsequence Sum

    题目链接:戳我 一类典型模型.线段树模拟网络流+区间最大K段和. 因为不会写,所以参考了黄学长的博客.但是我觉得他说得不够详细,所以想好好地解释一下: 前置技能1:区间最大子段和 如果K=1的时候怎么 ...

  8. emacs 考场配置

    先存在这里,免得等回来乱搞的时候把自己的配置搞丢了qwq (custom-set-variables '(custom-enabled-themes (quote (tango-dark)))) (c ...

  9. CYJian的水题大赛2 解题报告

    这场比赛是前几天洛谷上 暮雪﹃紛紛dalao的个人公开赛,当时基本上都在水暴力分......也没有好好写正解(可能除了T1) 过了几天颓废的日子之后,本蒟蒻觉得应该卓越一下了qwq,所以就打算写一个解 ...

  10. toggleClass,toggle切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...