天天看點

反射基礎

反射概念:反射是由架構提供的一個類庫,可以通路dll的metadata,擷取的dll的資訊,并使用它

反射的命名空間:using System.Reflection;

DLL裡面包含了兩種:

1.IL中間語言,最後變成機器碼

2.metadata中繼資料,用于描述IL

程式結構:

Reflence引用DB.sqlserver DB.interface

DB.sqlserver引用DB.interface

接口配置:

普通實作方法:執行個體化

IDBserver dBserver =newsqlserverDBhelper();
dBserver.Query();      

效果

利用反射去實作:

//Assembly是反射的命名空間引入的類
Assembly assembly = Assembly.Load("DB.sqlserver");//動态加載dll沒有字尾
Type type = assembly.GetType("DB.sqlserver.sqlserverDBhelper");//擷取類型名稱 傳遞完整類型
Object obj = Activator.CreateInstance(type);//建立對象
((sqlserverDBhelper)obj).Query();//調用方法
Console.ReadLine();      

如果每增加一個類就要重新指定DLL名稱,配置性不高

為了增加程式的可配置性,建立一個工廠類

如果程式需要讀取配置檔案就需要引入一個DLL

引入命名空間 using System.Configuration;
配置檔案添加,鍵值對      
<appSettings>
<add key="IDBHelperType" value="DB.sqlserver,DB.sqlserver.sqlserverDBhelper"></add>
</appSettings>      
publicclassObjectFactroy
{
//根據key名字擷取,讀取到目前項
privatestatic string IDBHelperType = ConfigurationManager.AppSettings["IDBHelperType"];
publicstatic string DLLName = IDBHelperType.Split(',')[0];//擷取DLL名稱
publicstatic string TypeName = IDBHelperType.Split(',')[1];//擷取檔案名
publicstatic IDBserver CreateInstance()
{
            Assembly assembly = Assembly.Load(DLLName);
            Type type = assembly.GetType(TypeName);//擷取類型名稱 傳遞完整類型
            Object obj = Activator.CreateInstance(type);//建立對象
return(IDBserver)obj;
}
}      

有需要變更直接在配置檔案更改value值

Main 函數調用

IDBserver bserver = ObjectFactroy.CreateInstance();
bserver.Query();      

1.怎樣讓程式可配置可擴充呢,在不改變原來代碼的條件下增加一個類庫

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DB.Interface;
namespace DB.Oracle
{
publicclassOracleDBhelper: IDBserver
{
publicOracleDBhelper()
{
            Console.WriteLine("{0}被構造",this.GetType().Name);
}
publicvoidQuery()
{
            Console.WriteLine("{0},Query",this.GetType().Name);
}
}
}      

修改配置檔案指向新的DLL

上述已經配置好接口類型,第三方依賴注入的容器會幫你完成建立

實際上這就是IOC,業務邏輯層提供一個接口進行IOC的配置

此時

1.去掉接口,反射調用方法

此時調用的是Query的無參數構造方法

Assembly assembly = Assembly.Load("DB.sqlserver");//動态加載dll沒有字尾
Type type = assembly.GetType("DB.sqlserver.sqlserverDBhelper");//擷取類型名稱 傳遞完整類型
Object obj = Activator.CreateInstance(type);//建立對象
MethodInfo method = type.GetMethod("Query",newType[]{});
method.Invoke(obj,newobject[]{});      

仔細觀察發現這也是MVC方法響應的原理,DLL在程式最初已經編譯好,MVC路徑:/控制器/方法。隻需要指定方法就能随意跳轉頁面

模仿控制器傳入方法的多種參數

Assembly assembly = Assembly.Load("DB.sqlserver");//動态加載dll沒有字尾
            Type type = assembly.GetType("DB.sqlserver.sqlserverDBhelper");//擷取類型名稱 傳遞完整類型
            Object obj = Activator.CreateInstance(type);//建立對象
{
{
                    MethodInfo method = type.GetMethod("Query",newType[]{});
                    method.Invoke(obj,newobject[]{});
}
{
                    MethodInfo method = type.GetMethod("Query",newType[]{typeof(string)});
                    method.Invoke(obj,newobject[]{"AB"});
}
{
                    MethodInfo method = type.GetMethod("Query",newType[]{typeof(int)});
                    method.Invoke(obj,newobject[]{20});
}
{
                    MethodInfo method = type.GetMethod("Query",newType[]{typeof(string),typeof(int)});
                    method.Invoke(obj,newobject[]{"AB",20});
}
{
                    MethodInfo method = type.GetMethod("Query",newType[]{typeof(int),typeof(string)});
                    method.Invoke(obj,newobject[]{20,"AB"});
}
}      

反射最大的優點:動态加載、不需要引用命名空間

缺點:編寫麻煩,避開了編譯器的檢查不到錯誤

利用反射擷取屬性和方法

寫死的方法:

People people =newPeople()
{
     id=10,
     Name="YLC"
};
people.Property ="字段";
Console.WriteLine("id:{0}",people.id);
Console.WriteLine("Name:{0}", people.Name);
Console.WriteLine("Property:{0}", people.Property);      

這個時候如果增加一個屬性,代碼又需要修改,增加100個就要列印100 Console.WriteLine();

利用反射自帶的進行實作

Type type =typeof(People);
foreach(var item in type.GetProperties())//擷取屬性
{
                object obj = item.GetValue(people);
                Console.WriteLine("{0}:{1}",item.Name,obj);
}

foreach(var item in type.GetFields())//擷取字段
{
                object obj = item.GetValue(people);
                Console.WriteLine("{0}:{1}", item.Name, obj);
}      

效果相同