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

C# Assembly.Load案例詳解

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

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

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

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

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

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

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

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

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

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

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

//Load assembly using byte array

Assembly assembly = Assembly.Load(buffer);

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

如果你需要通過上面的方法加載GAC 中的程序集,那么可以通過如下代碼實(shí)現(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)程序集時(shí),可能有各種情況導(dǎo)致加載失敗,最常見的是目標(biāo)程序集不存在而導(dǎo)致加載失敗問題。失敗后我們可能想要再加載一次或者加載多次直到成功為止,但是在.NET Framework 2.0 以后默認(rèn)是無法實(shí)現(xiàn)的,原因在于.NET Framework 2.0 以后 Assembly.Load 方法有緩存,第一次加載目標(biāo)程序集的失敗或者成功的狀態(tài)都會(huì)被緩存,這樣在你下一次加載目標(biāo)程序集時(shí)不會(huì)真的加載,會(huì)直接從緩存里取目標(biāo)程序集的內(nèi)容和狀態(tài)。

對(duì)這種情況我們可以在調(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

因?yàn)槟壳癆ssembly 的加載與卸載是完全由應(yīng)用程序域控制的,一個(gè)程序集只可以通過應(yīng)用程序域加載,只能通過應(yīng)用程序域的卸載而卸載,其他任何方式都不可以?。?!

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

到目前為止,看似無解了,但是我們忽略了一個(gè)事實(shí),那就是我們可以在當(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. 我們確實(shí)需要使用Assembly.Load嗎?

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

微軟在.Net Framework 2.0 時(shí)介紹了幾個(gè)新的程序集加載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)用任何綁定策略。

使用時(shí)有如下幾個(gè)注意事項(xiàng):

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

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

詳細(xì)請(qǐng)參考: http://m.fzitv.net/article/221129.htm

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

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

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

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

3) 一旦出現(xiàn)加載錯(cuò)誤,不要顯而易見認(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

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

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

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

    阳泉市| 嘉兴市| 天长市| 石家庄市| 双江| 布拖县| 阿拉善右旗| 原阳县| 盘山县| 田东县| 开封县| 丰县| 永济市| 曲沃县| 竹北市| 区。| 陆丰市| 张掖市| 新巴尔虎左旗| 呼伦贝尔市| 南通市| 灵武市| 商水县| 六盘水市| 唐山市| 班戈县| 澄城县| 巴青县| 建阳市| 庄河市| 易门县| 大田县| 桐庐县| 隆林| 平安县| 舞阳县| 磐安县| 霍林郭勒市| 吴旗县| 青田县| 西峡县|