C#高级编程 第十五章 反射

(二)自定义特性

使自定义特性非常强大的因素时使用反射,代码可以读取这些元数据,使用它们在运行期间作出决策。

1、编写自定义特性

定义一个FieldName特性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class FieldNameAttribute : Attribute
{
    private string name;
    public FieldNameAttribute(string name)
    {
        this.name = name;
    }
}

(1)AttributeUsage特性

特性类本身用一个特性——System.AttributeUsage特性来标记。AttributeUsage第一个参数用于标识自定义特性可以应用到那些类型的程序元素上,其类型是枚举类型AttrubuteTargets。

当应用类型超过1个时,可以用OR运算符连接:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
AllowMultiple属性用于指定该特性是否可以多次应用于同一项上,当设置为false,以下编码会报错:
[FieldName("我的属性1")]
[FieldName("我的属性2")]
public int MyProperty { get; set; }
Inherited属性用于指示使用该特性的类或类成员能否由派生类或重写成员继承。

(2)指定特性参数

编译器会检查传递给特性的参数,并查找该特性中带这些参数的构造函数。一半仅提供一个构造函数,使用属性来定义任何其他可选参数。

(3)指定特性的可选参数

另一种语法,可把可选参数添加到特性中。这种语法指定可选参数的名称和值,它通过特性类中的公共属性或字段起作用。例如上述代码中AttributeUsage特性使用的AllowMultiple和Inherited就是使用的这种语法。

(三)反射

通过System.Type类可以访问关于任何数据类型的信息。System.Reflection.Assembly类可以用于访问给定程序集的相关信息,或者把这个程序集加载到程序中。

1、System.Type类

Type有与每种数据类型对应的派生类。获取指定任何给定类型的Type引用有3中常用方式:

使用C#的typeof运算符:

Type type = typeof(double);

使用GetType()方法(所有的类都会从System.Object继承这个方法):

double d = 10.0;
Type type = d.GetType();

使用Type类的静态方法GetType():

Type type = Type.GetType("System.Double");

(1)Type的属性

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         Type intType = typeof(int);
 6         Console.WriteLine("当前类型的类型名:"+intType.Name);
 7         Console.WriteLine("当前类型的类型完全限定名:" + intType.FullName);
 8         Console.WriteLine("当前类型的名称空间名:" + intType.Namespace);
 9         Console.WriteLine("当前类型的直接基类名:" + intType.BaseType);
10         Console.WriteLine("当前类型的.NET运行库中映射到的类型:" + intType.UnderlyingSystemType);
11         Console.WriteLine("是否为数组的:" + intType.IsArray);
12         Console.WriteLine("是否为值类型:" + intType.IsValueType);
13     }
14 }
15 public class MyBaseClass { }
16 public class MyClass : MyBaseClass { }

运行以上代码,结果如下:

还有很多IsXXX来判断是否为某种类型。

(2)方法

System.Type类的大多数方法都用于获取对应数据类型的成员信息:构造函数、属性、方法和事件。后缀加‘s’的表示获取当前数据类型中所有的成员相关信息,不加则只获取数据类型中一个成员的相关信息。

Type intType = typeof(int);
var method = intType.GetMethod("GetHashCode");
var methods = intType.GetMethods();
foreach (var item in methods)
{}

System.Type类还包含有GetConstructor()方法和GetConstructors()等

时间: 2024-10-11 21:52:39

C#高级编程 第十五章 反射的相关文章

【读书笔记】C#高级编程 第十五章 反射

(一)在运行期间处理和检查代码 自定义特性允许把自定义元数据与程序元素关联起来.反射是一个普通术语,它描述了在运行过程中检查和处理程序元素的功能.例如,反射允许完成的任务: 枚举类型的成员 实例化新对象 执行对象的成员 查找程序集的信息 检查应用于某种类型的自定义特性 创建和编译新程序集 (二)自定义特性 使自定义特性非常强大的因素时使用反射,代码可以读取这些元数据,使用它们在运行期间作出决策. 1.编写自定义特性 定义一个FieldName特性: [AttributeUsage(Attribu

【读书笔记】C#高级编程 第二十五章 事务处理

(一)简介 事务的主要特征是,任务要么全部完成,要么都不完成. (二)概述 事务由事务管理器来管理和协调.每个影响事务结果的资源都由一个资源管理器来管理.事务管理器与资源管理器通信,以定义事务的结果. 1.事务处理阶段 激活阶段:在这个阶段创建事务. 准备阶段:在这个阶段,每个资源管理器都可以定义事务的结果. 提交阶段:当所有的资源管理器都成功准备好了,就开始这个阶段. 2.ACID属性 事务的特征可以用术语ACID来定义: Atomicity(原子性):表示一个工作单元. Consistenc

【读书笔记】C#高级编程 第十六章 错误和异常

(一)简介 错误的出现并不总是编写应用程序的人的原因,有时应用程序会因为应用程序的最终用户引发或运行代码的环境而发生错误.C#提供了异常处理机制来处理错误. (二)异常类 在C#中,但刚出现某个特殊的异常错误条件时,就会创建(或抛出)一个异常对象.一般情况下异常没有特定的名称空间,异常类应放在生成异常的类所在的名称空间. (三)捕获异常 .NET Framework提供了大量的预定义基类异常对象.为了在C#代码中处理可能的错误情况,一般要把程序的相关部分分成3种不同类型的代码块. try块包含的

【读书笔记】C#高级编程 第二十二章 安全性

(一)身份验证和授权 安全性的两个基本支柱是身份验证和授权.身份验证是标识用户的过程,授权在验证了所标识用户是否可以访问特性资源之后进行的. 1.标识和Principal 使用标识可以验证运行应用程序的用户.Principal是一个包含用户的标识和用户所属角色的对象. AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); var principal = WindowsPrincipal.Curr

读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

读书笔记 - js高级程序设计 - 第十三章 事件 canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好 有时候即使浏览器支持,操作系统如果缺缺乏必要的绘图驱动程序,则浏览器即使支持了也没用   <canvas> var drawing = document.getElementById("drawing"); if( drawing.getContext ){ drawing.getContext("2d"

【读书笔记】C#高级编程 第二十四章 文件和注册表操作

(一)文件和注册表 对于文件系统操作,相关的类几乎都在System.IO名称空间中,而注册表操作由System.Win32名称空间中的类来处理. (二)管理文件系统 System.MarshalByRefObject--这是.NET类中用于远程操作的基对象类,它允许在应用程序域之间编组数据. FileSystemInfo--这是表示任何文件系统对象的基类. FileInfo和File--这些类表示文件系统上的文件. DirectoryInfo和Directory--这些类表示文件系统上的文件夹.

【读书笔记】C#高级编程 第十四章 内存管理和指针

(一)后台内存管理 1.值数据类型 Windows使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址,该任务由Windows在后台管理(32位每个进程可使用4GB虚拟内存,64位更多,这个内存包括可执行代码和加载的DLL,以及程序运行时使用的变量内容). 在处理器的虚拟内存中,有一个区域称为栈.栈存储不是对象成员的值数据类型. 释放变量时,其顺序总是与它们分配内存的顺序相反,这就是栈的工作方式. 程序第一次运行时,栈指针指向为栈保留的内存块末尾.栈实际上是向下填充的,即从

【读书笔记】C#高级编程 第十二章 动态语言扩展

(一)DLR C#4的动态功能是Dynamic Language Runtime(动态语言运行时,DLR)的一部分.DLR是添加到CLR的一系列服务. (二)dynamic类型 dynamic类型允许编写忽略编译期间的类型检查的代码.编译器假定,给dynamic类型的对象定义的任何操作都是有效的,在运行之前编译器不会检测是否存在错误. 例子: dynamic person = "人"; string firstName = person.FirstName; 这两行代码能够通过编译器编

C#高级编程七十五天----C#使用指针

在C#中使用指针的语法 假设想在C#中使用指针,首先对项目进行过配置: 看到属性了吗?单击: 看到那个同意不安全代码了吗?选中 然后将有关指针,地址的操作放在unsafe语句块中.使用unsafekeyword是告诉编译器这里的代码是不安全的. unsafekeyword的使用: (1)放在函数前,修饰函数,说明在函数内部或函数的形參涉及到指针操作: unsafe static void FastCopy(byte[] src, byte[] dst, int count) { // Unsaf