reflection; 程序集包含模塊,而模塊包含類型,類型又包含成員。反射則提供了封裝程序集、模塊和類型的對象。我們可以使用反射動態地創建類型的實例,將類型綁定到現有對象,或從現有對象中獲取類型。然后,就可以調用類型的方法或訪問其字段和屬性。
下圖很好的解釋了程序集和模塊,類型等之間的關系:
//Assembly通過此類可以加載操縱一個程序集,并獲取程序集內部信息
Assembly assembly = Assembly.Load("MyAssembly"); //引用命名空間
Assembly assembly2 = Assembly.LoadFrom("D:\testDll.dll");
Assembly dll = Assembly.LoadFile(Environment.CurrentDirectory + "\\testDll.dll"); //通過dll文件去反射其中所有的類型,但不會加載引用的程序集
Type math = Type.GetType("testDll.Math", true); //獲取類型
MethodInfo method = math.GetMethod("add"); //獲取testdll.math中的方法add
int count = (int)method.Invoke(null, new object[] { 10, 20 }); //給add方法傳參數并去調用方法add
Console.WriteLine("Invoke Method:" + count.ToString());
Console.ReadLine();
Assembly dll = Assembly.LoadFile(Environment.CurrentDirectory + "\\testDll.dll"); //通過dll文件去反射其中所有的類型,但不會加載引用的程序集
//Environment.CurrentDirectory 屬性:獲取或設置當前工作目錄的完全限定路徑
Type math = dll.GetType("testDll.Math", true); //獲取類型
MethodInfo method = math.GetMethod("add"); //獲取testdll.math中的方法add
int count = (int)method.Invoke(null, new object[] { 10, 20 }); //給add方法傳參數并去調用方法add
Console.WriteLine("Invoke Method:" + count.ToString());
Console.ReadLine();
在不用反射+配置文件時,抽象工廠的問題是:
*如果需要增加多個數據庫,就要增加多個類,更麻煩。
在使用反射+配置文件后,抽象工廠的改變是:
*如果需要更換數據庫,不需改變代碼,只需要修改配置文件中DB的值。
小結:反射技術的使用去除了switch或if,解除分支判斷的耦合。在這里,反射可以說是簡化了工廠的實現。
//EF:就是讓EF上下文保存了一下。不適合于集群(后期使用key,value保存在分布式緩存中,key為guid)
public int SaveChanges()
{
//return DbContextFactory.GetCurrentDbContext().SaveChanges();
string strAssembly = ConfigurationManager.AppSettings["DalAssembly"];
string strDbContextFactoryclassFulleName = ConfigurationManager.AppSettings["DbContextFactoryclassFulleName"];
Assembly assembly = Assembly.Load(strAssembly);
Type type = assembly.GetType(strDbContextFactoryclassFulleName);
MethodInfo methodInfo = type.GetMethod("GetCurrentDbContext");
return ((DbContext)methodInfo.Invoke(null, null)).SaveChanges();
}
反射與引用
相比較下,引用執行效率高,但是當你引用的dll文件很多的時候,一遍遍的引用dll...,那就不是什么好事了。 反射呢,雖執行效率低,但在上述情況出現時,它只需動態反射一次dll文件,不用去管dll文件時新增還是減少的情況了,有點一勞永逸的味道。
在真正用的過程中,反射回合委托,泛型,特性等等結合使用,這都是需要進一步研究學習的地方