最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C# Assembly.Load案例詳解

 更新時間:2021年08月31日 18:11:59   作者:未風(fēng)  
這篇文章主要介紹了C# Assembly.Load案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

 我們在使用C# 語言的Assembly.Load 來加載托管程序集并使用反射功能時,一般需要先通過Assembly.Load(), Assembly.LoadFrom() 等方法將目標(biāo)托管程序集加載到當(dāng)前應(yīng)用程序域中,然后生成對應(yīng)實例,最后再進(jìn)行調(diào)用實例的屬性或者方法。

一般情況下,我們調(diào)用Assembly.Load 一類方法是不會出問題的,但是對于以下幾種情況Assembly.Load 方法無法處理:

  1. 程序集可能是延遲簽名的。
  2. 程序集可能被CAS 策略保護(hù)。
  3. 宿主程序與目標(biāo)程序集的處理器架構(gòu)不同。
  4. 當(dāng)加載目標(biāo)程序集時,目標(biāo)程序集中的方法可能正在運(yùn)行。 (比如,模塊初始化)
  5. 程序集可能應(yīng)用了綁定策略, 你可能不會得到你想要的那個程序集。

我們現(xiàn)在關(guān)注第四種情況,因為這種情況是最常見的。我們思考以下幾個問題:

1. 為什么目標(biāo)程序集的方法在運(yùn)行時不允許再加載一次?

準(zhǔn)確地說是為什么在一個應(yīng)用程序域(AppDomain)中加載后的程序集默認(rèn)不允許再另外一個應(yīng)用程序域中加載?這是因為在第一次加載應(yīng)用程序集時,Assemlby.Load 方法會將此程序集鎖住,以防止在自己使用過程中應(yīng)用程序集被其他應(yīng)用程序修改(一般指刪除)。這其實與Win32 API 中的CreateFile 函數(shù)行為類似,我們都知道,在 Windows 中去占用一個文件最直接、最簡單的方式就是調(diào)用 CreateFile API 函數(shù)來打開文件。具體請參照:

http://www.fzitv.net/article/221122.htm 

2. Assembly.Load 方法能否實現(xiàn)在加載目標(biāo)程序集時不鎖定它?

我們可以使用如下代碼加載我們的程序集:

byte[] buffer = System.IO.File.ReadAllBytes(yourFullfileNamePath);

//Load assembly using byte array

Assembly assembly = Assembly.Load(buffer);

后臺的實現(xiàn)是暫時先將目標(biāo)程序集鎖定,然后把程序集內(nèi)容復(fù)制到內(nèi)存中,讀取后將程序集解鎖并從內(nèi)存中加載目標(biāo)程序集的拷貝。

如果你需要通過上面的方法加載GAC 中的程序集,那么可以通過如下代碼實現(xiàn):

string assemblyName = "AssemblyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fffb45e56dd478e3";

Assembly ass = Assembly.ReflectionOnlyLoad(assemblyName);

byte[] buffer = System.IO.File.ReadAllBytes(ass.Location);

Assembly assembly = Assembly.Load(buffer);

3. Assembly.Load 方法的緩存

在我們使用Assembly.Load 系列方法加載目標(biāo)程序集時,可能有各種情況導(dǎo)致加載失敗,最常見的是目標(biāo)程序集不存在而導(dǎo)致加載失敗問題。失敗后我們可能想要再加載一次或者加載多次直到成功為止,但是在.NET Framework 2.0 以后默認(rèn)是無法實現(xiàn)的,原因在于.NET Framework 2.0 以后 Assembly.Load 方法有緩存,第一次加載目標(biāo)程序集的失敗或者成功的狀態(tài)都會被緩存,這樣在你下一次加載目標(biāo)程序集時不會真的加載,會直接從緩存里取目標(biāo)程序集的內(nèi)容和狀態(tài)。

對這種情況我們可以在調(diào)用Assembly.Load 方法的宿主程序的app.config 中加入如下配置信息來禁用緩存:

<?xml version="1.0"?>
<configuration>
  <runtime>
    <disableCachingBindingFailures enabled="1" />
  </runtime>
  <startup>
    <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>

4. 還有其他方案嗎?

CLR 框架略圖:

CLR

因為目前Assembly 的加載與卸載是完全由應(yīng)用程序域控制的,一個程序集只可以通過應(yīng)用程序域加載,只能通過應(yīng)用程序域的卸載而卸載,其他任何方式都不可以?。?!

那么我們可以在需要時將目標(biāo)程序集加載進(jìn)應(yīng)用程序域,不需要時將應(yīng)用程序域卸載,但是當(dāng)前應(yīng)用程序域的卸載只能通過關(guān)閉程序來實現(xiàn)。

到目前為止,看似無解了,但是我們忽略了一個事實,那就是我們可以在當(dāng)前應(yīng)用程序域中創(chuàng)建子應(yīng)用程序域??梢酝ㄟ^在子應(yīng)用程序域中進(jìn)行程序集的加載,或者說只要涉及程序集加載的全部放在子應(yīng)用程序域中,主應(yīng)用程序域中不做任何與程序集加載有關(guān)的事情。

這部分內(nèi)容我就不詳細(xì)介紹了,大家可以參考:

http://www.codeproject.com/Articles/42312/Loading-Assemblies-in-Separate-Directories-Into-a

5. 我們確實需要使用Assembly.Load嗎?

因為Assembly.Load 是將整個程序集以及其相關(guān)的依賴程序集全部加載進(jìn)來,只要有一個出錯就會導(dǎo)致加載失敗。如果我們只是為了使用當(dāng)前程序集的類型,而不是使用其方法或者屬性的話就完全可以拋棄Assembly.Load 方法。

微軟在.Net Framework 2.0 時介紹了幾個新的程序集加載APIs:

Assembly.ReflectionOnlyLoadFrom(String assemblyFile)

Assembly.ReflectionOnlyLoad(byte[] rawAssembly)

Assembly.ReflectionOnlyLoad(String assemblyName)

基于開篇提到的Assembly.Load 方法的5種問題, Reflection Only程序集加載APIs 可以:

  1. 跳過程序集強(qiáng)命名認(rèn)證。
  2. 跳過程序集CAS策略認(rèn)證。
  3. 跳過處理器架構(gòu)檢查規(guī)則。
  4. 不在目標(biāo)程序中執(zhí)行任何方法,包括構(gòu)造函數(shù)。
  5. 不應(yīng)用任何綁定策略。

使用時有如下幾個注意事項:

1) CLR 不會搜索目標(biāo)程序集所依賴的程序集,我們必須通過ReflectionOnlyAssemblyResolve(Assembly.Load 中的對應(yīng)事件是AssemblyResolve)事件手動處理。

2) 不可以在通過ReflectionOnly 方法加載進(jìn)來的程序集執(zhí)行任何方法,包括構(gòu)造函數(shù),只可以獲取程序集的信息和類型。

3) 建議使用Assembly.ReflectionOnlyLoadFrom 方法,但是如果目標(biāo)程序集在GAC中那么可以使用Assembly.ReflectionOnlyLoad方法。

具體示例代碼如下:

using System;
using System.IO;
using System.Reflection;

public class ReflectionOnlyLoadTest
{
    private String m_rootAssembly;
    public ReflectionOnlyLoadTest(String rootAssembly)
    {
        m_rootAssembly = rootAssembly;
    }

    public static void Main(String[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("Usage: Test assemblyPath");
            return;
        }

        try
        {
            ReflectionOnlyLoadTest rolt = new ReflectionOnlyLoadTest(args[0]);
            rolt.Run();
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: {0}!!!", e.Message);
        }
    }

    internal void Run()
    {
        AppDomain curDomain = AppDomain.CurrentDomain;
        curDomain.ReflectionOnlyAssemblyResolve += 
            new ResolveEventHandler(MyReflectionOnlyResolveEventHandler);
        Assembly asm = Assembly.ReflectionOnlyLoadFrom(m_rootAssembly);
        // force loading all the dependencies
        Type[] types = asm.GetTypes();
        // show reflection only assemblies in current appdomain
        Console.WriteLine("------------- Inspection Context --------------");
        foreach (Assembly a in curDomain.ReflectionOnlyGetAssemblies())
        {
            Console.WriteLine("Assembly Location: {0}", a.Location);
            Console.WriteLine("Assembly Name: {0}", a.FullName);
            Console.WriteLine();
        }
    }

    private Assembly MyReflectionOnlyResolveEventHandler(object sender, ResolveEventArgs args)
    {
        AssemblyName name = new AssemblyName(args.Name);
        String asmToCheck = Path.GetDirectoryName(m_rootAssembly) + "\\" + name.Name + ".dll";
        if (File.Exists(asmToCheck))
        {
            return Assembly.ReflectionOnlyLoadFrom(asmToCheck);
        }

        return Assembly.ReflectionOnlyLoad(args.Name);
    }
}

6. 為什么沒有Assembly.UnLoad 方法?

以下是CLR 產(chǎn)品單元經(jīng)理(Unit Manager) Jason Zander 文章中的內(nèi)容的整理:

  1) 為了保證 CLR 中代碼所引用的代碼地址都是有效的,必須跟蹤諸如 GC 對象和 COM CCW 之類的特殊應(yīng)用。否則會出現(xiàn) Unload 一個 Assembly 后,還有 CLR 對象或 COM 組件使用到這個 Assembly 的代碼或數(shù)據(jù)地址,進(jìn)而導(dǎo)致訪問異常。為了避免這種錯誤進(jìn)行的跟蹤,目前是在 AppDomain 一級進(jìn)行的,如果要加入 Assembly.Unload 支持,則跟蹤的粒度必須降到 Assembly 一級,這雖然在技術(shù)上不是不能實現(xiàn),但代價太大了。   2) 如果支持 Assembly.Unload 則必須跟蹤每個 Assembly 的代碼使用到的句柄和對現(xiàn)有托管代碼的引用。例如現(xiàn)在 JITer 在編譯方法時,生成代碼都在一個統(tǒng)一的區(qū)域,如果要支持卸載 Assembly 則必須對每個 Assembly 都進(jìn)行獨(dú)立編譯。此外還有一些類似的資源使用問題,如果要分離跟蹤技術(shù)上雖然可行,但代價較大,特別是在諸如 WinCE 這類資源有限的系統(tǒng)上問題比較明顯。   3) CLR 中支持跨 AppDomain 的 Assembly 載入優(yōu)化,也就是 domain neutral 的優(yōu)化,使得多個 AppDomain 可以共享一份代碼,加快載入速度。而目前 v1.0 和 v1.1 無法處理卸載 domain neutral 類型代碼。這也導(dǎo)致實現(xiàn) Assembly.Unload 完整語義的困難性。

詳細(xì)請參考: http://www.fzitv.net/article/221129.htm

http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx

7. 需要牢記的經(jīng)驗

1) 只加載自己需要直接調(diào)用的程序集,不加載目標(biāo)程序集內(nèi)部引用的程序集和其他無關(guān)程序集。

2) 能使用RefelectionLoad 方法加載的程序集絕不要使用Assembly.Load 方法加載。

3) 一旦出現(xiàn)加載錯誤,不要顯而易見認(rèn)為是程序集不存在!要檢查程序集加載緩存、是否出現(xiàn)同一程序集被不同應(yīng)用程序域加載情況等。

至此,我們已經(jīng)闡述了Assembly.Load 方法的一些特性,你已經(jīng)了解它了嗎?

參考鏈接:

http://msdn.microsoft.com/en-us/library/t07a3dye(v=vs.71).aspx

http://blogs.msdn.com/b/junfeng/archive/2004/11/03/252033.aspx

http://blogs.msdn.com/b/junfeng/archive/2004/08/24/219691.aspx

http://www.sosuo8.com/article/show.asp?id=2979

http://msdn.microsoft.com/en-us/library/ms404279.aspx

http://blog.csdn.net/xt_xiaotian/article/details/6362450

http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx

http://www.cnblogs.com/ccBoy/archive/2004/07/13/23636.html

http://www.cnblogs.com/wayfarer/archive/2004/09/29/47896.html

http://www.codeproject.com/Articles/42312/Loading-Assemblies-in-Separate-Directories-Into-a

http://msdn.microsoft.com/en-us/library/ms404312.aspx

到此這篇關(guān)于C# Assembly.Load案例詳解的文章就介紹到這了,更多相關(guān)C# Assembly.Load內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#使用NOPI庫實現(xiàn)導(dǎo)入Excel文檔

    C#使用NOPI庫實現(xiàn)導(dǎo)入Excel文檔

    NPOI中N指代的是.Net,POI是一個完全開源的Java寫成的庫,能夠在沒有安裝微軟Office或者相應(yīng)環(huán)境的情況下讀寫Excel、Word等微軟OLE2組件文檔,幾乎支持所有的Office97~Office2007的文件格式。所以NPOI就是POI項目的.Net版本。
    2017-05-05
  • 最新評論

    安化县| 噶尔县| 阳城县| 姚安县| 河池市| 颍上县| 怀来县| 泸定县| 哈尔滨市| 新乐市| 锡林郭勒盟| 北辰区| 宜章县| 沙田区| 小金县| 江阴市| 陆良县| 遂昌县| 阿坝县| 广河县| 林口县| 玉山县| 龙陵县| 合阳县| 长海县| 黄骅市| 嵊泗县| 治县。| 达日县| 社旗县| 黄骅市| 乌兰浩特市| 保康县| 西乌| 吴堡县| 天峨县| 奉化市| 都兰县| 光泽县| 平谷区| 榕江县|