1. 基本瞭解
1.1 反射概述
文字說明
審查後設資料並收集關於它的型別資訊的能力稱為反射,其中後設資料(編譯以後的最基本資料單元)就是一大堆的表,當編譯程式集或者模組時,編譯器會建立一個類定義表,一個欄位定義表,和一個方法定義表等
反射提供了封裝程式集、模組和型別的物件(Type
型別),可以使用反射動態建立型別的例項,將型別繫結到現有物件,或從現有物件獲取型別並呼叫其方法或訪問其欄位和屬性。如果程式碼中使用了屬性,可以利用反射對它們進行訪問
實際上
反射是微軟封裝的一個幫助類庫:using System.Reflection;
1.2 反射用途
- 使用
Assembly
定義和載入程式集,載入在程式集清單中列出模組,以及從此程式集中查詢型別並建立該型別的例項 - 使用
Module
瞭解包含模組的程式集以及模組中的類等,還可以獲取在模組上定義的所有全域性方法或其他特定的非全域性方法 - 使用
ConstructorInfo
瞭解建構函式的名稱、引數、訪問修飾符(如pulic
或private
)和實現詳細資訊(如abstract
或virtual
)等;使用Type
的GetConstructors
或GetConstructor
方法來呼叫特定的建構函式 - 使用
MethodInfo
瞭解方法的名稱、返回型別、引數、訪問修飾符(如pulic
或private
)和實現詳細資訊(如abstract
或virtual
)等;使用Type
的GetMethods
或GetMethod
方法來呼叫特定的方法 - 使用
FiedInfo
瞭解欄位的名稱、訪問修飾符(如public
或private
)和實現詳細資訊(如static
)等,並獲取或設定欄位值。 - 使用
EventInfo
瞭解事件的名稱、事件處理程式資料型別、自定義屬性、宣告型別和反射型別等,新增或移除事件處理程式。 - 使用
PropertyInfo
瞭解屬性的名稱、資料型別、宣告型別、反射型別和只讀或可寫狀態等,獲取或設定屬性值 - 使用
ParameterInfo
瞭解引數的名稱、資料型別、是輸入引數還是輸出引數,以及引數在方法簽名中的位置等
1.3 反射常用類
反射是一個程式集發現及執行的過程,通過反射能夠得到 .exe
或.dll
等程式集內部的資訊,使用反射能夠看到一個程式集內部的介面、類、方法、欄位、屬性、特性等資訊
型別 | 描述 |
---|---|
Assembly | 通過此類能夠載入操縱一個程式集,並獲取程式集內部資訊 |
FieldInfo | 該類儲存給定的欄位資訊 |
MethodInfo | 該類儲存給定的方法資訊 |
MemberInfo | 該類是一個基類,定義了EventInfo,FieldInfo,MethodInfo,PropertyInfo的多個公用行為 |
Module | 該類能夠使你能訪問多個程式集中的給定模組 |
ParameterInfo | 該類儲存給定的引數資訊 |
PropertyInfo | 該類儲存給定的屬性資訊 |
2. Assembly 程式集物件
2.1 物件簡介
官方文件
程式集包含模組、模組包含型別,而型別包含成員。 反射提供封裝程式集、模組和型別的物件。 可以使用反射動態地建立型別的例項,將型別繫結到現有物件,或從現有物件中獲取型別
其它文件
System.Reflection.Assembly
:表示一個程式集
程式集是程式碼進行編譯是的一個邏輯單元,把相關的程式碼和型別進行組合,然後生成PE檔案(例如可執行檔案.exe
和類庫檔案.dll
)
由於程式集在編譯後並不一定會生成單個檔案,而可能會生成多個物理檔案,甚至可能會生成分佈在不同位置的多個物理檔案,所以程式集是一個邏輯單元,而不是一個物理單元;即程式集在邏輯上是一個編譯單元,但在物理儲存上可以有多種存在形式
對於靜態程式集可以生成單個或多個檔案,而動態程式集是存在於記憶體中的
在C#中程式集處處可見,因為任何基於.NET的程式碼在編譯時都至少存在一個程式集(所有.NET專案都會預設引用mscorlib
程式集)
程式集包含了兩種檔案:可執行檔案(.exe
檔案)和 類庫檔案(.dll
檔案)
在VS開發環境中,一個解決方案可以包含多個專案,而每個專案就是一個程式集
2.2 應用程式結構
包含應用程式域(AppDomain
),程式集(Assembly
),模組(Module
),型別(Type
),成員(EventInfo、FieldInfo、MethodInfo、PropertyInfo
) 幾個層次
2.3 靜態方法
常用靜態方法
方法 | 返回值型別 | 描述 |
---|---|---|
Assembly.Load | Assembly | 載入相對路徑下指定名稱程式集 |
Assembly.LoadFile | Assembly | 根據全路徑獲取指定程式集 |
Assembly.LoadFrom | Assembly | 根據全路徑獲取指定程式集 |
2.4 例項方法,屬性
常用例項屬性
屬性 | 屬性值型別 | 描述 |
---|---|---|
assembly.FullName | string | 獲取程式集的顯示名稱 |
assembly.Location | string | 獲取程式集的完整路徑(全名稱) |
assembly.DefinedTypes | IEnumerable |
獲取定義在程式集中型別集合 |
assembly.Modules | IEnumerable |
獲取定義在程式集中模組集合 |
常用例項方法
方法 | 返回值 | 描述 |
---|---|---|
assembly.GetTypes() | Type[] | 獲取程式集中定義的型別陣列 |
assembly.GetType() | Type | 獲取程式集中定義的型別 |
assembly.GetExportedTypes() | Type[] | 獲取程式集中定義的所有公共型別(類,介面,列舉等) |
assembly.CreateInstance() | object | 根據傳入型別建立型別例項 |
2.5 示例:載入程式集
方式一:
Load
,c2
引用了Helper
,有引用關係
using System;
using System.Reflection;
using Helper;
namespace c2
{
class Program
{
static void Main(string[] args)
{
// 相對路徑下載入指定名稱程式集檔案
Assembly assembly = Assembly.Load("Helper");
}
}
}
示例二:
LoadFile
,c2
與taskdao
無引用關係
using System;
using System.Reflection;
namespace c2
{
class Program
{
static void Main(string[] args)
{
// 根據全名稱(路徑+檔名.字尾)下載入指定名稱程式集檔案
Assembly assembly =
Assembly.LoadFile(@"E:\SolutionZX\taskdao\bin\Debug\taskdao.dll");
}
}
}
示例三:
LoadFrom
,c2
與taskdao
無引用關係
using System;
using System.Reflection;
namespace c2
{
class Program
{
static void Main(string[] args)
{
// 根據全名稱(路徑+檔名.字尾)下載入指定名稱程式集檔案
Assembly assembly =
Assembly.LoadFrom(@"E:\SolutionZX\taskdao\bin\Debug\taskdao.dll");
}
}
}
示例四:根據型別建立型別例項,
c2
與taskdao
無引用關係
dynamic
型別為動態型別,使用時編譯器不會檢查(執行時檢查)
using System;
using System.Reflection;
namespace c2
{
class Program
{
static void Main(string[] args)
{
// 根據全名稱(路徑+檔名.字尾)下載入指定名稱程式集檔案
Assembly assembly =
Assembly.LoadFrom(@"E:\SolutionZX\taskdao\bin\Debug\taskdao.dll");
// object _t = assembly.CreateInstance("task1dao.task1");
// 報錯,object型別識別不出Show方法,因為C#是強型別語言
// _t.Show();
dynamic _t = assembly.CreateInstance("task1dao.task1");
_t.Show();
}
}
}
2.6 獲取型別
獲取普通型別
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.UserInfo");
獲取泛型型別
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.UserInfo`1"); // UserInfo`1 英文狀態下數字1左邊符號,引數個數
3. Type 型別
在C#中可以理解為一個類對應一個Type
物件
3.1 例項屬性,方法
例項屬性
屬性 | 屬性值型別 | 描述 |
---|---|---|
type.Name | string | 獲取型別名稱(類名) |
type.FullName | string | 獲取類全名(名稱空間+類名稱) |
type.Namespace | string | 獲取類所在的名稱空間 |
type.Assembly | string | 獲取類所在程式集名稱 |
type.BaseType | Type | 獲取基類(父類) |
type.IsSubclassOf(Type parent) | bool | type是否是parent的子類 |
type.IsInstanceOfType(object o) | bool | o是否是type類的物件 |
type.IsClass | bool | 獲取物件型別是否是類 |
type.IsInterface | bool | 獲取物件型別是否是介面 |
type.IsNotPublic | bool | 獲取物件型別是否公開 |
type.IsAbstract | bool | 獲取物件型別是否是抽象的 |
type.IsSealed | bool | 獲取物件型別是否是密封的 |
type.IsArray | bool | 獲取物件型別是否是陣列 |
type.IsEnum | bool | 獲取物件型別是否是列舉 |
例項方法
方法 | 返回值型別 | 描述 |
---|---|---|
type.GetMembers() | MemberInfo[] | 獲取型別中所有公共成員 |
type.GetMethods() | MethodInfo[] | 獲取所有公共方法(包含基類) |
type.GetConstructors() | ConstructorInfo[] | 獲取型別中所有公共建構函式 |
type.GetFields() | FieldInfo[] | 獲取所有公共欄位 |
type.GetProperties() | PropertyInfo[] | 獲取所有公共屬性 |
type.GetInterfaces() | Type[] | 獲取所有公共介面 |
type.MakeGenericType(...) | Type | 設定泛型類,泛型引數型別 |
type.GetMember(...) | MemberInfo[] | 多個,獲取公共成員(不常用) |
type.GetMethod(...) | MethodInfo | 單個,獲取公共方法 |
type.GetConstructor(...) | ConstructorInfo | 單個,獲取公共方法 |
type.GetField(...) | FieldInfo | 單個,獲取公共欄位 |
type.GetProperty(...) | PropertyInfo | 單個,獲取公共屬性 |
type.GetInterface(...) | Type | 單個,獲取公共介面 |
type.IsDefined(...) | bool | 獲取此型別是否繼承指定特性 |
type.GetCustomAttributes(...) | object[] | 獲取此型別指定特性陣列 |
3.2 操作示例一
public class Base
{
}
public interface Inta { }
public interface Intb { }
public class UserInfo<A> : Base, Inta, Intb
{
#region 公共建構函式
public UserInfo()
{
Console.WriteLine("無參構造方法...");
}
public UserInfo(int id)
{
Console.WriteLine("1個引數構造方法");
}
#endregion
#region 私有建構函式
private UserInfo(string name) { }
#endregion
#region 公共欄位
public string code;
#endregion
#region 私有欄位
private string msg;
#endregion
#region 公共屬性
public int id { get; set; }
#endregion
#region 公共方法
public void Print()
{
Console.WriteLine("無引數例項方法");
}
public void Show()
{
Console.WriteLine("無引數過載例項方法");
}
public void Show(int id)
{
Console.WriteLine("有引數過載例項方法-" + id.ToString());
}
#endregion
#region 公共靜態方法
public static void Statc() { }
#endregion
#region 私有方法
private void GetM()
{
Console.WriteLine("無引數私有方法");
}
private void GetM(int i)
{
Console.WriteLine("有引數私有方法-" + id.ToString());
}
#endregion
#region 公共泛型方法
public void GenericC(A a)
{
Console.WriteLine("公共泛型無參方法:" + a.ToString());
}
public void GenericS<T>()
{
Console.WriteLine("公共泛型無參方法");
}
public void GenericsA<T>(A a, T t)
{
Console.WriteLine("公共泛型有參方法:" + t.ToString() + "\t" + a.ToString());
}
#endregion
}
通過類獲得對應的
Type
Type type = typeof(UserInfo);
通過
Assembly
物件,通過類的fullname
類獲得Type
物件
Assembly assem = Assembly.LoadFrom(@"E:\SolutionRP\DMO\bin\Debug\DMO.dll");
Type type = assem.GetType("DMO.UserInfo");
綜合示例
Type type = typeof(UserInfo);
Console.WriteLine("型別名:" + type.Name);
Console.WriteLine("類全名:" + type.FullName);
Console.WriteLine("名稱空間名:" + type.Namespace);
Console.WriteLine("程式集名:" + type.Assembly);
Console.WriteLine("模組名:" + type.Module);
Console.WriteLine("基類名:" + type.BaseType);
Console.WriteLine("是否類:" + type.IsClass);
MethodInfo method = type.GetMethod("Show");//獲得例項的方法
Console.WriteLine("類的公共成員:");
MemberInfo[] memberInfos = type.GetMembers();//得到所有公共成員
foreach (var item in memberInfos)
{
Console.WriteLine("成員型別:" + item.MemberType + "\t成員:" + item);
}
3.3 示例二:獲取公共方法
一:獲取所有公共成員
static void Main(string[] args)
{
Type type = typeof(UserInfo);
Console.Write("獲取所有公共成員:");
MemberInfo[] members = type.GetMembers();
Console.WriteLine(members.Length);
Console.Write("獲取所有公共方法(包含基類):");
MethodInfo[] methods = type.GetMethods();
Console.WriteLine(methods.Length);
Console.Write("獲取所有公共建構函式:");
ConstructorInfo[] constructors = type.GetConstructors();
Console.WriteLine(constructors.Length);
Console.Write("獲取所有公共欄位:");
FieldInfo[] fields = type.GetFields();
Console.WriteLine(fields.Length);
Console.Write("獲取所有公共屬性:");
PropertyInfo[] properties = type.GetProperties();
Console.WriteLine(properties.Length);
Console.Write("獲取所有公共介面:");
Type[] interfaces = type.GetInterfaces();
Console.WriteLine(interfaces.Length);
}
根據名稱獲取公共成員(不常用)
MemberInfo[] memberInfo1 = type.GetMember("code");
MemberInfo[] memberInfo2 = type.GetMember("Show");
Console.WriteLine(memberInfo1.Length);
Console.WriteLine(memberInfo2.Length);
根據名稱獲取公共方法
// 獲取公共方法(非過載方法)
MethodInfo methodInfo1 = type.GetMethod("Print");
Console.WriteLine(methodInfo1.Name);
// 獲取公共過載方法,根據引數順序,型別,個數獲取
// 1.呼叫有一個int型別引數的過載方法
MethodInfo methodInfo2 = type.GetMethod("Show", new Type[] { typeof(int) });
// 2.呼叫無引數過載方法(不可傳null)
MethodInfo methodInfo3 = type.GetMethod("Show", new Type[0]);
Console.WriteLine(methodInfo3.Name);
根據引數的型別,數量,順序返回指定構造方法
// 返回無參公共構造方法
ConstructorInfo constructor1 = type.GetConstructor(new Type[0]);
// 返回有一個int型別引數的公共構造方法
ConstructorInfo constructor2 = type.GetConstructor(new Type[] { typeof(int) });
獲取型別公共欄位
FieldInfo fieldInfo1 = type.GetField("code");
Console.WriteLine(fieldInfo1.Name);
獲取型別公共屬性
PropertyInfo propertyInfo1 = type.GetProperty("id");
Console.WriteLine(propertyInfo1.Name);
3.4 示例三:獲取靜態方法
3.5 示例四:獲取泛型方法
獲取泛型方法
Assembly assembly = typeof(Program).Assembly;
// 獲取有一個泛型引數的類
Type type = assembly.GetType("c2.UserInfo`1");
// 指定泛型引數型別
Type generictype = type.MakeGenericType(new Type[] { typeof(int) });
object oType = Activator.CreateInstance(generictype);
3.6 示例五:獲取特性
[CustomAttribute]
public class Studen
{
public void Show()
{
}
}
public class CustomAttribute : Attribute
{
}
static void Main(string[] args)
{
Type type = typeof(Studen);
if(type.IsDefined(typeof(CustomAttribute), true))
{
object[] oAttrbute = type.GetCustomAttributes(typeof(CustomAttribute), true);
Console.WriteLine(oAttrbute.Length);
}
}
4. MethodInfo 方法
一個 MethodInfo
表示一個方法(公共,私有,靜態,構造)
4.1 例項屬性,方法
例項屬性
屬性 | 屬性值型別 | 描述 |
---|---|---|
methodInfo.Name | string | 方法名稱 |
methodInfo.ReturnType | Type | 獲取方法返回值型別 |
methodInfo.IsConstructor | bool | 是否是構造方法 |
methodInfo.IsAbstract | bool | 是否為抽象方法 |
methodInfo.IsPrivate | bool | 是否為私有方法 |
methodInfo.IsPublic | bool | 是否為公共方法 |
methodInfo.IsStatic | bool | 是否為靜態方法 |
methodInfo.IsVirtual | bool | 是否為虛方法 |
methodInfo.IsGenericMethod | bool | 是否為泛型方法 |
例項方法
方法 | 返回值 | 描述 |
---|---|---|
methodInfo.Invoke(...) | object | 呼叫非泛型方法 |
methodInfo.GetParameters() | ParameterInfo[] | 獲取方法引數陣列 |
methodInfo.IsDefined(...) | bool | 獲取此方法是否繼承指定特性 |
methodInfo.GetCustomAttributes(...) | object[] | 獲取此方法指定特性陣列 |
4.2 操作示例一
獲取呼叫非泛型非過載無引數方法,無引數方法第二個引數可傳
null
,但不推薦
Type type = typeof(UserInfo);
object oType = Activator.CreateInstance(type);
MethodInfo methodInfo = null;
methodInfo = type.GetMethod("Print");
methodInfo.Invoke(oType,new object[0]);
methodInfo.Invoke(oType, null);
獲取呼叫非泛型過載無引數方法,無引數方法第二個引數可傳
null
,但不推薦
Type type = typeof(UserInfo);
object oType = Activator.CreateInstance(type);
MethodInfo methodInfo = null;
methodInfo = type.GetMethod("Show",new Type[0]);
methodInfo.Invoke(oType,new object[0]);
methodInfo.Invoke(oType, null);
獲取呼叫非泛型過載有引數方法,多個引數用逗號隔開,引數型別,個數,順序必須相同
Type type = typeof(UserInfo);
object oType = Activator.CreateInstance(type);
MethodInfo methodInfo = null;
methodInfo = type.GetMethod("Show", new Type[] { typeof(int) });
methodInfo.Invoke(oType, new object[] { 1 });
4.3 操作示例二
獲取泛型方法與獲取普通方法一致,泛型引數按從左到右順序傳入,方法引數型別與泛型引數型別一致
呼叫公共泛型無參方法
// 獲取泛型方法
MethodInfo methodInfo = type.GetMethod("GenericS");
// 指定泛型方法引數
MethodInfo genericmethod = methodInfo.MakeGenericMethod(new Type[] { typeof(int) });
genericmethod.Invoke(oType, null);
呼叫公共泛型有參方法
MethodInfo methodInfo = type.GetMethod("GenericsA");
MethodInfo genericsmethod =
methodInfo.MakeGenericMethod(new Type[] { typeof(int), typeof(string) });
genericsmethod.Invoke(oType, new object[] { 1 });
呼叫公共泛型類的有參方法,泛型類中的泛型引數與泛型方法的泛型引數一致
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.UserInfo`1");
Type generictype = type.MakeGenericType(new Type[] { typeof(int) });
object oType = Activator.CreateInstance(generictype);
MethodInfo methodInfo = generictype.GetMethod("GenericC");
methodInfo.Invoke(oType, new object[] { 1 });
}
呼叫公共泛型類的有參方法,泛型類中的泛型引數與泛型方法的泛型引數不一致
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.UserInfo`1");
Type generictype = type.MakeGenericType(new Type[] { typeof(int) });
object oType = Activator.CreateInstance(generictype);
MethodInfo methodInfo = generictype.GetMethod("GenericsA");
MethodInfo genericsmethodinfo =
methodInfo.MakeGenericMethod(new Type[] { typeof(string) });
genericsmethodinfo.Invoke(oType, new object[] { 2, "af" });
}
5. ConstructorInfo 建構函式
5.1 例項屬性,方法
例項方法
方法 | 返回值型別 | 描述 |
---|---|---|
constructor.Invoke(...) | object | 執行建構函式 |
constructor.IsDefined(...) | bool | 獲取此建構函式是否繼承指定特性 |
constructor.GetCustomAttributes(...) | object[] | 獲取此建構函式指定特性陣列 |
5.2 操作例項一
public class User
{
public User()
{
Console.WriteLine("無參建構函式");
}
public User(string n)
{
Console.WriteLine("有參建構函式:" + n);
}
}
呼叫建構函式
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.User");
object oType = Activator.CreateInstance(type);
ConstructorInfo constructor = type.GetConstructor(new Type[0]);
constructor.Invoke(oType, null);
ConstructorInfo constructor1 = type.GetConstructor(new Type[] { typeof(string) });
constructor1.Invoke(oType, new object[] { "liai" });
ParameterInfo[] parameters = constructor1.GetParameters();
Console.WriteLine(parameters.Length);
}
6. PropertyInfo 屬性
6.1 例項屬性,方法
例項屬性
屬性 | 屬性值型別 | 描述 |
---|---|---|
property.Name | string | 獲取屬性名稱 |
property.CanRead | bool | 獲取屬性是否可讀 |
property.CanWrite | bool | 獲取屬性是否可寫 |
property.PropertyType | Type | 獲取屬性型別 |
例項方法
方法 | 返回值型別 | 描述 |
---|---|---|
property.SetValue(...) | void | 設定物件屬性 |
property.GetValue(...) | object | 獲取物件屬性值 |
property.IsDefined(...) | bool | 獲取此屬性是否繼承指定特性 |
property.GetCustomAttributes(...) | object[] | 獲取此屬性指定特性陣列 |
6.2 操作例項一
獲取公共屬性
// 獲取所有
PropertyInfo[] propertys = type.GetProperty();
// 獲取指定
PropertyInfo property = type.GetProperty("no");
獲取屬性,設定屬性值,獲取屬性值
class Program
{
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.Order");
object oType = Activator.CreateInstance(type);
PropertyInfo property = type.GetProperty("no");
property.SetValue(oType,1);
var value = property.GetValue(oType);
Console.WriteLine(value);
}
}
public class Order
{
public int no { get; set; }
}
7. FieldInfo 欄位
7.1 例項屬性,方法
例項屬性
屬性名 | 屬性值型別 | 描述 |
---|---|---|
field.Name | string | 獲取欄位名稱 |
field.Is... | bool | 獲取欄位是否為... |
field.FieldType | Type | 獲取欄位型別 |
例項方法
方法 | 返回值型別 | 描述 |
---|---|---|
field.IsDefined(...) | bool | 獲取此欄位是否繼承指定特性 |
field.GetCustomAttributes(...) | object[] | 獲取此欄位指定特性陣列 |
7.2 操作例項一
獲取欄位
class Program
{
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.Order");
object oType = Activator.CreateInstance(type);
FieldInfo field = type.GetField("name");
FieldInfo[] fields = type.GetFields();
}
}
public class Order
{
public string name;
}
獲取值,設定值
class Program
{
static void Main(string[] args)
{
Assembly assembly = typeof(Program).Assembly;
Type type = assembly.GetType("c2.Order");
object oType = Activator.CreateInstance(type);
FieldInfo field = type.GetField("name");
field.SetValue(oType, "libai");
var value = field.GetValue(oType);
Console.WriteLine(value);
}
}
public class Order
{
public string name;
}
8. 擴充套件補充
8.1 載入程式集
獲得當前【應用程式域】中的所有程式集
Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();
獲得當前物件所屬的類所在的程式集
Assembly assembly = this.GetType().Assembly;
Assembly.LoadFile
與Assembly.LoadFrom
的差別
LoadFile
方法用來載入和檢查具有同樣標識但位於不同路徑中的程式集,但不會載入程式的依賴項LoadFrom
不能用於載入標識同樣但路徑不同的程式集
建立例項物件
此方法的作用與 new
一個例項物件相同
Activator.CreateInstance(type)
8.2 Module 程式集模組
Assembly assembly = Assembly.Load("mscorlib");//載入程式集
Module module = assembly.GetModule("CommonLanguageRuntimeLibrary");//得到指定模組
Console.WriteLine("模組名:" + module.Name);
Type[] types = module.FindTypes(Module.FilterTypeName, "Assembly*");
foreach (var item in types)
{
Console.WriteLine("類名:" + item.Name);//輸出型別名
}
Console.Read();
8.3 BindingFlags說明
列舉值 | 描述 |
---|---|
BindingFlags.Instance | 物件例項 |
BindingFlags.Static | 靜態成員 |
BindingFlags.Public | 指可在搜尋中包含公共成員 |
BindingFlags.NonPublic | 指可在搜尋中包含非公共成員(即私有成員和受保護的成員) |
BindingFlags.FlattenHierarchy | 指可包含層次結構上的靜態成員 |
BindingFlags.IgnoreCase | 表示忽略 name 的大小寫 |
BindingFlags.DeclaredOnly | 僅搜尋 Type 上宣告的成員,而不搜尋被簡單繼承的成員 |
BindingFlags.CreateInstance | 表示呼叫建構函式。忽略 name。對其他呼叫標誌無效 |
8.4 屬性應用:ORM
簡易實現
public Order Find(int id)
{
string sql = "select id,name,createTime from order where id = " +id;
Type type = typeof(Order);
object oOrder = Activator.CreateInstance(type);
using (SqlConnection connection = new SqlConnection("constr"))
{
SqlCommand cmd = new SqlCommand(sql,connection);
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
foreach (var prop in type.GetProperties())
{
prop.SetValue(oOrder,prop.Name);
}
}
}
return (Order)oOrder;
}
// DTD
public class Order
{
public int no { get; set; }
public string name { get; set; }
public DateTime createTime { get; set; }
}
泛型版本
public T Find<T>(int id) where T : BaseEntity
{
string sql = "select id,name,createTime from order where id = " + id;
Type type = typeof(T);
object oOrder = Activator.CreateInstance(type);
using (SqlConnection connection = new SqlConnection("constr"))
{
SqlCommand cmd = new SqlCommand(sql, connection);
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
foreach (var prop in type.GetProperties())
{
prop.SetValue(oOrder, prop.Name);
}
}
}
return (T)oOrder;
}
public class BaseEntity { }
public class Order:BaseEntity
{
public int no { get; set; }
public string name { get; set; }
public DateTime createTime { get; set; }
}