02.反射Reflection


1. 基本了解

1.1 反射概述

文字說明

審查元數據並收集關於它的類型信息的能力稱為反射,其中元數據(編譯以后的最基本數據單元)就是一大堆的表,當編譯程序集或者模塊時,編譯器會創建一個類定義表,一個字段定義表,和一個方法定義表等

反射提供了封裝程序集、模塊和類型的對象(Type 類型),可以使用反射動態創建類型的實例,將類型綁定到現有對象,或從現有對象獲取類型並調用其方法或訪問其字段和屬性。如果代碼中使用了屬性,可以利用反射對它們進行訪問

實際上

反射是微軟封裝的一個幫助類庫:using System.Reflection;

1.2 反射用途

  • 使用Assembly定義和加載程序集,加載在程序集清單中列出模塊,以及從此程序集中查找類型並創建該類型的實例
  • 使用Module了解包含模塊的程序集以及模塊中的類等,還可以獲取在模塊上定義的所有全局方法或其他特定的非全局方法
  • 使用ConstructorInfo了解構造函數的名稱、參數、訪問修飾符(如pulicprivate)和實現詳細信息(如abstractvirtual)等;使用TypeGetConstructorsGetConstructor方法來調用特定的構造函數
  • 使用MethodInfo了解方法的名稱、返回類型、參數、訪問修飾符(如pulicprivate)和實現詳細信息(如abstractvirtual)等;使用TypeGetMethodsGetMethod方法來調用特定的方法
  • 使用FiedInfo了解字段的名稱、訪問修飾符(如publicprivate)和實現詳細信息(如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 示例:加載程序集

方式一:Loadc2 引用了 Helper,有引用關系

using System;
using System.Reflection;
using Helper;

namespace c2
{
    class Program
    {
        static void Main(string[] args)
        {
            // 相對路徑下加載指定名稱程序集文件
            Assembly assembly = Assembly.Load("Helper");
        }
    }
}

示例二:LoadFilec2taskdao無引用關系

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");
        }
    }
}

示例三:LoadFromc2taskdao無引用關系

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");
        }
    }
}

示例四:根據類型創建類型實例,c2taskdao無引用關系

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.GetCustomAttributes(...) object[] 獲取此類型指定特性數組
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.GetCustomAttribute(...) Attribute 單個,獲取此類型指定特性

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))
    {
        // 如果有多個相同特性,默認取首個
        Attribute attribute = type.GetCustomAttribute(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.GetCustomAttribute(...) Attribute 單個,獲取指定特性
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.GetCustomAttribute(...) Attribute 單個,獲取指定特性
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.GetCustomAttribute(...) Attribute 單個,獲取指定特性
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.GetCustomAttribute(...) Attribute 單個,獲取指定特性
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.LoadFileAssembly.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; }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM