前些天在看到了很多地方用到了反射就想好好看一下這個。
反射的一些知識
反射描述了在運行過程中檢查和處理程序元素的功能
應用:可以在程序運行的時候檢索出程序中的東西,在版本控制的時候也有用。
反射涉及到的一些知識 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"/
$False$
*這個也要傳給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<br /> {
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");
&nbs 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);
}
}
}