前些天在看到了很多地方用到了反射就想好好看一下这个。
反射的一些知识
反射描述了在运行过程中检查和处理程序元素的功能
应用:可以在程序运行的时候检索出程序中的东西,在版本控制的时候也有用。
反射涉及到的一些知识 Type,Assembly,Attribute
Type 为 System.Reflection 功能的根,也是访问元数据的主要方式。Type的成员用于获取关于类型声明的信息,如构造函数、方法、字段、
属性 (Property) 和类的事件,以及在其中部署该类的模块和程序集。知道它是获取程序集中的对象的有关类型就可以了。
获取给定类型的type引用有3种方法typeof(),gettype,Type.GetType()第3个是静态方法
属性有name fullname 还有个要用的就是 i.IsClass如果类型是class的话就返回true
它的方法有GetMethod() GetMethods()获取相关类型中的方法,一个返回一个方法,一个返回一个方法的数组,类型为methodinfo
GetMember()和GetMember() 返回的是数据类型的所有成员的信息
Assembly类是在System.Reflection命名空间中定义的,它允许用户访问给定程序集的元数据,它也包含可以加载和执行程序集(假定该程序集
是可执行的) 的方法。与Type类一样,Assembly类包含非常多的方法和属性.
Load() LoadFrom()。这两个方法的区别是Load()的参数是程序集的名称,运行库会在各个位置上搜索该程序集,这些位置包括本地目录和全局
程序集高速缓存。而LoadFrom()的参数是程序集的完整路径名,不会在其他位置搜索该程序集.
Assembly.GetTypes() 返回一个包含所有类型信息的System.Type引用数组
Attribute 表示自定义属性的基类。在System命名空间中,我们写自己特性类要继承这个类
GetCustomAttributes() 是个静态的方法 用于获取程序集中的所有特性 可以这样写
Attribute [] definedAttributes=Attribute.GetCustomAttributes(assembly1);表示获取assembly1程序集中的所有特性
Attribute [] definedAttributes=Attribute.GetCustomAttributes(assembly1,typeof(一个类型));返回程序集中这个类型的所有的定制特
性
下面是c#高级编程中的例子
我对这个例子理解是 假如过写了一段代码,后来又向这个代码中加了一些方法,属性,类之类,现在我想知道加入这些方法的时间,和这些方
法的用途,肯定不能象我们写代码那样有提示的,因为程序已经变成了.dll,这个时候就用反射来获取其中的元数据。
先在我们知道方法修改时间的地方标志上[LastModified("10 Feb 2002", "Method added in order to provide formatting support")]这个
(我们需要知道的东西都要在这里写上,这样你随便加代码我都可以知道你什么时间加的了只要你写了这个标记)它调用我们写的特性类中的
构造函数来实例化。之后在我们需要在代码出利用Assembly的load方法把程序集VectorClass加载上,然后在其中查找我们的自己的特性,查到
的话它自己就会调用我们自己写的特性类中的构造函数进行实例化,最后我们需要做的就是利用GetMethod(),GetMember()等获取我们需要知
道的信息了。
代码如下
应用了特性类的程序集VectorClass
using System;
using Wrox.ProCSharp.WhatsNewAttributes;//引用前面的空间
using System.Collections;
using System.Text;
[assembly: SupportsWhatsNew]//标记程序集本身的代码,表示特性应用到程序集
namespace Wrox.ProCSharp.VectorClass
{
[LastModified("14 Feb 2002"/*这个要传给我们写的特性类LastModifiedAttribute中的构造函数,动态实例化指定的特性*/,
"IEnumerable interface implemented " +
"So Vector can now be treated as a collection"/*这个也要传给LastModifiedAttribute中的构造函数*/)]
//LastModified也可以用LastModifiedAttribute,Attribute编译器会自己加上的,对应我们写的特性类
[LastModified("10 Feb 2002", "IFormattable interface implemented " +
"So Vector now responds to format specifiers N and VE")]//这里因为前面写的是AllowMultiple=true所以一个特性可以多次应用
到一个程序中
class Vector : IFormattable, IEnumerable//IFormattable提供将对象的值格式化为字符串表示形式的功能。重载tostring要用
//IEnumerable接口实现的是foreach循环, GetEnumerator方法需要重载。
{
public double x, y, z;
public Vector(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
[LastModified("10 Feb 2002", "Method added in order to provide formatting support")]//程序在检索到这个方法的时候会进
行这个特性的调用,这个时候会调用特性类的构造函数
public string ToString(string format, IFormatProvider formatProvider)//IFormattable中的方法
//IFormatProvider提供区域设置
{
if (format == null)
return ToString();
string formatUpper = format.ToUpper();
switch (formatUpper)
{
case "N":
return "|| " + Norm().ToString() + " ||";
case "VE":
return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
case "IJK":
StringBuilder sb = new StringBuilder(x.ToString(), 30);
sb.Append(" i + ");
sb.Append(y.ToString());
sb.Append(" j + ");
sb.Append(z.ToString());
sb.Append(" k");
return sb.ToString();
default:
return ToString();
}
}
public Vector(Vector rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
[LastModified("14 Feb 2002", "Method added in order to provide collection support")]
public IEnumerator GetEnumerator()//IEnumerable接口的GetEnumerator方法需要重载。
{
return new VectorEnumerator(this);
}
public override string ToString()
{
return "( " + x + " , " + y + " , " + z + " )";
}
public double this[uint i]
{
get
{
switch (i)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw new IndexOutOfRangeException(
"Attempt to retrieve Vector element" + i);
}
}
set
{
switch (i)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default:
throw new IndexOutOfRangeException(
"Attempt to set Vector element" + i);
}
}
}
public static bool operator ==(Vector lhs, Vector rhs)
{
if (System.Math.Abs(lhs.x - rhs.x) < double.Epsilon &&
System.Math.Abs(lhs.y - rhs.y) < double.Epsilon &&
System.Math.Abs(lhs.z - rhs.z) < double.Epsilon)
return true;
else
return false;
}
public static bool operator !=(Vector lhs, Vector rhs)
{
return !(lhs == rhs);
}
public static Vector operator +(Vector lhs, Vector rhs)
{
Vector Result = new Vector(lhs);
Result.x += rhs.x;
Result.y += rhs.y;
Result.z += rhs.z;
return Result;
}
public static Vector operator *(double lhs, Vector rhs)
{
return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
}
public static Vector operator *(Vector lhs, double rhs)
{
return rhs * lhs;
}
public static double operator *(Vector lhs, Vector rhs)
{
return lhs.x * rhs.x + lhs.y + rhs.y + lhs.z * rhs.z;
}
public double Norm()
{
return x * x + y * y + z * z;
}
#region enumerator class
[LastModified("14 Feb 2002", "Class created as part of collection support for Vector")]
private class VectorEnumerator : IEnumerator
{
Vector theVector; // Vector object that this enumerato refers to
int location; // which element of theVector the enumerator is currently referring to
public VectorEnumerator(Vector theVector)
{
this.theVector = theVector;
location = -1;
}
public bool MoveNext()
{
++location;
return (location > 2) ? false : true;
}
public object Current
{
get
{
if (location < 0 || location > 2)
throw new InvalidOperationException(
"The enumerator is either before the first element or " +
"after the last element of the Vector");
return theVector[(uint)location];
}
}
public void Reset()
{
location = -1;
}
}
#endregion
}
}
特性类
using System;
namespace Wrox.ProCSharp.WhatsNewAttributes
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = true, Inherited = false)]
//AttributeUsage这个是微软提供的一个特性,他的作用是表示定制特性可以应用到哪些类型的程序元素上,第一个参数是个枚举类型
AttributeTargets,
//它指定LastModifiedAttribute特性能够应用到类,方法中,后面2个参数可选表示一个特性是否可以多次应用到同一项目和是否支持继
承
//下面是我们自己的特性
public class LastModifiedAttribute : Attribute // 都要继承特性类 Attribute,还要注意
//的是 LastModified这个要对应VectorClass类中的相关的东西对应
{
//下面和我们写平常的类没有区别
private DateTime dateModified;
private string changes;
private string issues;
public LastModifiedAttribute(string dateModified, string changes)
{
this.dateModified = DateTime.Parse(dateModified);
this.changes = changes;
}
public DateTime DateModified
{
get
{
return dateModified;
}
}
public string Changes
{
get
{
return changes;
}
}
//不需要设置上面个的set访问器,因为上面的构造函数已经设置了
public string Issues
{
get
{
return issues;
}
set
{
issues = value;
}
}
}
[AttributeUsage(AttributeTargets.Assembly)]//这个表示可以对程序集应用属性。
public class SupportsWhatsNewAttribute : Attribute
{
}
}
测试部分
using System;
using System.Reflection;
using System.Windows.Forms;
using System.Text;
using Wrox.ProCSharp.VectorClass;
using Wrox.ProCSharp.WhatsNewAttributes;//引用前面2个命名空间
namespace Wrox.ProCSharp.LookUpWhatsNew
//这个是测试程序
{
class WhatsNewChecker
{
static StringBuilder outputText = new StringBuilder(1000);
static DateTime backDateTo = new DateTime(2002, 2, 1);
static void Main()
{
//Assembly在System.Reflection命名空间中,它允许访问给定程序集的元数据,也可以加载和执行程序集。
Assembly theAssembly = Assembly.Load("VectorClass");
//加载一个程序集。也可以用方法loadfrom,他的参数是一个路径地址
Attribute supportsAttribute = Attribute.GetCustomAttribute(theAssembly, typeof(SupportsWhatsNewAttribute));//检索
应用于程序集的自定义属性。参数指定程序集和要搜索的自定义属性的类型
//返回的是一个数组,该数组包括该特性类的所有特性,返回的是我们在whatsnewattributes中定制特性,检查VectorClass程序
集中是否有特性SupportsWhatsNewAttribute
string Name = theAssembly.FullName;//该程序集的全名,由以下部分组成://简单名称//版本号//加密密钥对//支持的区域性
//返回的格式如这个VectorClass, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
AddToMessage("Assembly: " + Name);
if (supportsAttribute == null)
{
AddToMessage(
"This assembly does not support WhatsNew attributes");
return;
}
else
AddToMessage("Defined Types:");
Type[] types = theAssembly.GetTypes();//获取程序集中定义的所有类型
foreach (Type definedType in types)//循环每个类型,把它加到stringbuilder中去以变显示
DisplayTypeInfo(theAssembly, definedType);
MessageBox.Show(outputText.ToString(),
"What/'s New since " + backDateTo.ToLongDateString());//要显示的信息,窗口的标题
Console.ReadLine();
}
//用来显示特性中的属性,方法的名字和类型等
static void DisplayTypeInfo(Assembly theAssembly, Type type)
{
// make sure we only pick out classes
if (!(type.IsClass))//看这个类型是不是一个类 不是类就返回
return;
AddToMessage("/nclass " + type.Name);//获取类名
Attribute[] attribs = Attribute.GetCustomAttributes(type);
//检索应用于程序集的自定义属性的数组。参数指定程序集。用与确定这个类中是否有相关的LastModifiedAttribute实例
if (attribs.Length == 0)
AddToMessage("No changes to this class");
else
foreach (Attribute attrib in attribs)
//Attribute表示自定义属性的基类。
WriteAttributeInfo(attrib);//用与显示类的特性
MethodInfo[] methods = type.GetMethods();//获取类中的方法
AddToMessage("CHANGES TO METHODS OF THIS CLASS:");
foreach (MethodInfo nextMethod in methods)
{
object[] attribs2 =
nextMethod.GetCustomAttributes(
typeof(LastModifiedAttribute), false);
if (attribs != null)
{
AddToMessage(
nextMethod.ReturnType + " " + nextMethod.Name + "()");//获取次方法的返回类型和名字
foreach (Attribute nextAttrib in attribs2)
WriteAttributeInfo(nextAttrib);//显示属性的特性
}
}
}
//把相关信息写进特性中
static void WriteAttributeInfo(Attribute attrib)
{
LastModifiedAttribute lastModifiedAttrib =
attrib as LastModifiedAttribute;// 可以看做是这个[LastModified("14 Feb 2002", "Method added in order to
provide collection support")]
if (lastModifiedAttrib == null)
return;
// check that date is in range
DateTime modifiedDate = lastModifiedAttrib.DateModified;
if (modifiedDate < backDateTo)//backDateTo是2002, 2, 1 只显示这个日期以后的修改
return;
AddToMessage(" MODIFIED: " +
modifiedDate.ToLongDateString() + ":");
AddToMessage(" " + lastModifiedAttrib.Changes);
if (lastModifiedAttrib.Issues != null)
AddToMessage(" Outstanding issues:" +
lastModifiedAttrib.Issues);
}
static void AddToMessage(string message)
{
outputText.Append("/n" + message);
}
}
}