假使我们目前要实现这样一个函数: 函数参数是Object,函数的功能就是执行这个类内所有参数为空的公有成员方法。那么显然, 我们需要运行时获取某个类中的所有成员方法. 反射为我们提供了可以这样做的工具.
您可以使用反射动态的(也就是在程序运行时)创建一个类型的实例, 绑定类型至现有的对象, 或是从现有对象中获取类型.
以下是一个反射利用GetType()的获知某个类型的信息的例子. 由于该方法是继承自Object类所以不需要using System.Reflection.
using System;
//using System.Reflection;
class Application {
public static void Main(string[] args) {
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
}
}
运行结果如下.
System.Int32
以下是利用反射, 获取某个程序集(Assembly)的信息的例子:
using System;
using System.Reflection;
class Application {
public static void Main(string[] args) {
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);
}
}
运行结果如下:
System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
特性是一个强劲的工具用以结合元数据, 或是声明信息.
所谓元数据(Metadata), 就是您在程序中定义的有关类型的信息. 所有基于.NET框架的程序都包含有一个元数据的集合, 用以描述定义在程序集里的类型和类型成员.
特性有如下的特质:
我觉得你可以简单的把这玩意理解成游戏里武器的附魔词缀, 比方说破旧的长剑什么的
在c#中, 您可以在中括号中写入特性的名称来声明特定的特性.
规定特性的语法如下:
[attribute(positional_parameters, name_parameter = value, ...)]
element
特性(Attribute)的名称和值是在方括号内规定的,放置在它所应用的元素之前。positional_parameters 规定必需的信息,name_parameter 规定可选的信息。
在本例中, 可串行化的特性将在类中加入特定的元素.
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
.NET框架提供了三种预定义特性, 分别是AttributeUsage, AttributeUsage, AttributeUsage.
您可以使用AttributeUsage来定义您自己的特性. 具体的内容将会在稍后提及.
它的语法如下:
[AttributeUsage(
validon,
AllowMultiple=allowmultiple,
Inherited=inherited
)]
其中:
请看如下的例子:
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
这个特性可以修饰类, 构造函数, 字段, 属性, 方法. 它是多用的.
语法如下:
[Conditional(
conditionalSymbol
)]
这个预定义特性标记了一个条件方法,其执行依赖于指定的预处理标识符。它会引起方法调用的条件编译.
如果您更新了您代码中的某些部分, 但出于某种缘由, 您依旧想保留旧的部分, 呢么您可以将旧的代码标记为Obsolete (过时的)
它的语法规则如下:
[Obsolete(
message
)]
[Obsolete(
message,
iserror
)]
其中
您也可以创建自定义的特性, 用于储存声明性质的信息. 其可以在运行时被检索.
创建并使用自定义特性包含如下四个步骤:
声明自定义特性
一个新的自定义特性应派生自 System.Attribute 类。
如下是一个创建自定义特性DeBugInfo的语法.
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
构建自定义特性
我们继续完成我们声明的DeBugInfo特性. 假设我们希望它储存如下的信息:
显然, 我们希望该特性必须包含前三种信息, 但可以选择是否包含后一种信息. 我们将我们的 DeBugInfo 类将带有三个用于存储前三个信息的私有属性和一个用于存储消息的公有属性。所以 bug 编号、开发人员名字和审查日期将是 DeBugInfo 类的必需的定位( positional)参数,消息将是一个可选的命名(named)参数。
具体语法示例如下:
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
{
private int bugNo;
private string developer;
private string lastReview;
public string message;
public DeBugInfo(int bg, string dev, string d)
{
this.bugNo = bg;
this.developer = dev;
this.lastReview = d;
}
public int BugNo
{
get
{
return bugNo;
}
}
public string Developer
{
get
{
return developer;
}
}
public string LastReview
{
get
{
return lastReview;
}
}
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
应用自定义特性
您可以直接将您的自定义特性放在元素之前来应用他们. 如
[DeBugInfo(55, "Zara Ali", "19/10/2012",
Message = "Return type mismatch")]
public double GetArea()
{
return length * width;
}
您也可以利用反射来获得您自己定义的特性.