C# 高级编程(笔记6)

第14章  反射

1.自定义特性(Attribute)

编译器在遇到代码中某个应用了自定义特性的元素时的处理过程:

eg:

[StringLength(50, ErrorMessageResourceType = typeof(res), ErrorMessageResourceName = "MAX_USER_NAME_LENGTH")]
public String UName { get; set; }

//当C#编译器发现这个属性(property)应用了一个StringLength特性时,首先会把字符串Attribute追加到这个名称的后面,形成一个组合名称StringLengthAttribute,然后在其搜索路径的所有名称空间(即在using语句中提及的名称空间)中搜索有指定名称的类。但要注意,如果用一个特性标记数据项,而该特性的名称以字符串Attribute结尾,编译器就不会把该字符串加到组合名称中,而是不修改该特性名。

//编译器会找到含有该名称的类,且这个类直接或间接派生自System.Attribute。编译器还认为这个类包含控制特性用法的信息,特别是:

a.特性可以应用到哪些类型的程序元素上(类、结构、属性和方法等)
b.它是否可以多次应用到同一个程序元素上
c.特性在应用到类或接口上时,是否由派生类和接口继承
d.这个特性有哪些必选和可选参数

----如果编译器找不到对应的特性类,或者找到一个这样的特性类,但使用特性的方式与特性类中的信息不匹配,编译器就会产生一个编译错误。

2.AttributeUsage 特性类

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
    public class FieldNameAttribute : Attribute
    {
        public FieldNameAttribute()
        {
        }
    }

//一个自定义的特性类FieldNameAttribute本身再用一个System.AttributeUsage特性类来标记。AttributeUsage特性类主要用于标识自定义特性可以应用到哪些类型的程序元素上。这些信息由它的第一个参数给出,该参数是必选的,其类型是枚举类型AttributeTargets。

//AttributeTargets枚举的成员中有两个值不对应于任何程序元素:Assembly和Module,表明该特性可以应用到整个程序集或模块中,而不是应用到代码中的一个元素上,在这种情况下,这个特性可以放在源代码的任何地方,但需要用关键字assembly或module作为前缀

    [assembly: SomeAssemblyAttribute(Parameters)]
    [module: SomeAssemblyAttribute(Parameters)]

3.System.Type类

Type类是一个抽象基类,只要实例化一个Type对象,实际上就实例化了Type的一个派生类,Type有与每种数据类型对应的派生类。

通常,获取指向任何给定类型的Type引用有3种常用方式:

a.使用C#的typeof运算符
   //获取编译时阶段某一类型的System.Type对象
  //typeof()参数只能是构架中已经定义好了的类型和自定义类型,不能是实例

Type t
= typeof(double); b.使用GetType()方法,所有的类都会从System.Object继承这个方法 //获取运行时阶段当前实例的类型
    //GetType()是实例方法
double d = 10.0; Type t = d.GetType(); c.调用Type类的静态方法GetType() Type t = Type.GetType("System.Double");

//Type是许多反射功能的入口,它实现许多方法和属性,可以使用Type确定数据的类型,但不能使用它修改该类型

Type还可以获取在其中定义该类型的程序集的引用:

Type t = typeof(Vector);
Assembly ass = new Assembly(t);

4.Assembly 类

Assembly类允许访问给定程序集的元数据,它也包含可以加载和执行程序集的方法【假定该程序集是可执行的】。与Type类一样,Assembly类包含非常多的方法与属性。

在使用Assembly实例做一些工作前,需要把相应的程序集加载到正在运行的进程中。为此,可以使用静态成员Assembly.Load()或Assembly.LoadFrom()。

a.Assembly.Load()      ---- 该方法的参数是程序集的名称,运行库会在各个位置上搜索该程序集,这些位置包括本地目录和全局程序集缓存
b.Assembly.LoadFrom()  ---- 该方法的参数是程序集的完整路径名,它不会在其他位置搜索该程序集

Assembly ass1 = Assembly.Load("SomeAssembly");
Assembly ass2 = Assembly.LoadFrom(@"C:\My Projects\software\SomeotherAssembly");

加载完一个程序集后,就可以使用它的各种属性进行查询,如:

a.查找在程序集中定义的类型

Type[] types = theAssembly.GetTypes();
foreach(Type t in types)
{
  ...
}


b.查找自定义特性

//得到指定程序集中所有自定义特性
Attribute[] attr = Attribute.GetCustomAttributes(theAssembly);
原文地址:https://www.cnblogs.com/notebook2011/p/2970343.html