?反射的概念
?反射遍歷成員
?用射調用類型成員
?屬性概念(Attribute)
?屬性的實例
?自定議屬性
?三個屬性
二次編輯一次運行
一次編譯後
反射
反射是編程的讀取與類型相關聯的元數據的行爲。通讀取元數據,可以瞭解它是什麼類型以及類型的成員。比如類中的屬性,方法,事件等。
所屬命名空間System.Reflection
反射-反射成員名稱
類
class Demo_Class
{
public Demo_Class(int i)
{
Console.WriteLine("構造函數:" + i);
}
public void Method(string s)
{
Console.WriteLine("A類參數爲:" + s);
}
public int i;
public string S
{
get; set;
}
}
調用
static void Main(string[] args)
{
Type type = typeof(Demo_Class);
MemberInfo[] MI = type.GetMembers(BindingFlags.NonPublic | BindingFlags.Public |BindingFlags .Instance );
foreach (MemberInfo mi in MI)
{
Console.WriteLine("名稱:{0},類型:{1}",mi.Name,mi.MemberType .ToString ());
}
}
運行結果
反射-用反射調用無參構造類型成員
class Demo_Class
{
public void Method(string s)
{
Console.WriteLine("A類參數爲:" + s);
}
}
class Program
{
static void Main(string[] args)
{
BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
Type t = typeof(Demo_Class);
ConstructorInfo Cons = t.GetConstructor(new Type[0]); //構造函數無參,所以構造函數無類型參數
object Obj = Cons.Invoke(null);//傳入的構造參數爲空,得到對象
object[] MethodPar = new object[] { “a” }; //方法的參數
MethodInfo mi = t.GetMethod(“Method”, bf);//得到方法
Console.WriteLine(mi.Invoke(Obj, MethodPar));
}
}
反射-用反射調用有參構造類型成員
class Demo_Class
{
public void Method(string s)
{
Console.WriteLine("A類參數爲:" + s);
}
}
class Program
{
static void Main(string[] args)
{
BindingFlags bf = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
Type t = typeof(Demo_Class);
ConstructorInfo Cons = t.GetConstructor(new Type[]{typeof(int)}); //構造函數有參,類型爲int
object Obj = Cons.Invoke(net object[]{123});//傳入的構造參數, 得到對象
object[] MethodPar = new object[] { “a” }; //方法的參數
MethodInfo mi = t.GetMethod(“Method”, bf);//得到方法
Console.WriteLine(mi.Invoke(Obj, MethodPar));
}
}
屬性-Attribute
Attribute非property(類的成員)
屬性提供功能強大的方法以將聲明信息與 C# 代碼(類型、方法、屬性等)相關聯。
屬性與程序實體關聯後,即可在運行時使用名爲“反射”的技術查詢屬性。
屬性以兩種形式出現:
1.一種是在公共語言運行庫 (CLR) 中定義的屬性。
2.另一種是可以創建的用於向代碼中添加附加信息的自定義屬性。此信息可在以後以編程方式檢索。
屬性具有以下特點:
1.屬性可向程序中添加元數據。元數據是嵌入程序中的信息,如編譯器指令或數據描述。
2.程序可以使用反射檢查自己的元數據。
3.通常使用屬性與 COM 交互。
一個例子:
[System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "MessageBoxW")]
public static extern int MessageBoxW([System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, [System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string lpText, [System.Runtime.InteropServices.InAttribute()] [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string lpCaption, uint uType);
static void Main(string[] args)
{
Console .WriteLine ( MessageBoxW(IntPtr .Zero , "確定嗎?", "提示",1));
}
自定義屬性
通過定義一個屬性類,可以創建您自己的自定義屬性。該屬性類直接或間接地從System. Attribute 派生,有助於方便快捷地在元數據中標識屬性定義。假設您要用編寫類或結構的程序員的名字標記類和結構。
[System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct,AllowMultiple=true ,Inherited =true ) ] //Author屬性只能用於類和結構,AllowMultiple是否允許多次用屬性,Inherited是這個屬性是滯延續到子類。
public class Author : System.Attribute
{
private string name;
public double version;
public Author(string name)
{
this.name = name; version = 1.0;
}
}
[Author(“張三”, version =2.0)]//張三是Author的構造函數的參數,version是字段
class SampleClass
{ }
三個特別的屬性
1.AttributeUsage屬性(上面的例子已經演示)
2.Conditional屬性
3.Obsolete屬性
三個特別的屬性- Conditional
條件方法必須是類或結構聲明中的方法,而且必須具有 void 返回類型。
#define TRACE_ON //這行標識代碼決定着紅色代碼的執行與否。
using System;
using System.Diagnostics;
namespace R_A_Demo
{
public class Trace
{
[Conditional("TRACE_ON")]
public static void Msg(string msg)
{
Console.WriteLine(msg);
}
}
public class ProgramClass
{
static void Main()
{
Trace.Msg(“調試信息”);
Console.WriteLine(“代碼正體");
}
}
}
另一種用法
#define TRACE_ON
using System;
using System.Diagnostics;
namespace R_A_Demo
{
public class Trace
{
#if TRACE_ON
public static void Msg(string msg)
{
Console.WriteLine(msg);
}
#endif
}
public class ProgramClass
{
static void Main()
{
Trace.Msg("Now in Main...");
Console.WriteLine("Done.");
}
}
}
三個特別的屬性- Obsolete
[System.Obsolete("use class B")] //類會被在實例化時警告
class A
{
public void Method() { }
}
class B
{
[System.Obsolete("use NewMethod", false )] //方法調用時提示信息
public void OldMethod() { }
[System.Obsolete("use NewMethod", true)] //不可編譯
public void NewMethod() { }
}
一句話總結:
反射:利用一次編譯後的結果,反得到類型和類型成員。
屬性(Attribute):額外給其他類型添加信息的類型。