亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C# Assembly.Load案例詳解

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

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

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

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

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

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

準(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://chabaoo.cn/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)程序集加載進應(yīng)用程序域,不需要時將應(yīng)用程序域卸載,但是當(dāng)前應(yīng)用程序域的卸載只能通過關(guān)閉程序來實現(xiàn)。

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

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

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

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

因為Assembly.Load 是將整個程序集以及其相關(guā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. 跳過程序集強命名認(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 方法加載進來的程序集執(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ù)地址,進而導(dǎo)致訪問異常。為了避免這種錯誤進行的跟蹤,目前是在 AppDomain 一級進行的,如果要加入 Assembly.Unload 支持,則跟蹤的粒度必須降到 Assembly 一級,這雖然在技術(shù)上不是不能實現(xiàn),但代價太大了。   2) 如果支持 Assembly.Unload 則必須跟蹤每個 Assembly 的代碼使用到的句柄和對現(xiàn)有托管代碼的引用。例如現(xiàn)在 JITer 在編譯方法時,生成代碼都在一個統(tǒng)一的區(qū)域,如果要支持卸載 Assembly 則必須對每個 Assembly 都進行獨立編譯。此外還有一些類似的資源使用問題,如果要分離跟蹤技術(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 完整語義的困難性。

詳細請參考: http://chabaoo.cn/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#生成二維碼的方法

    C#生成二維碼的方法

    這篇文章主要介紹了C#生成二維碼的方法,包括動態(tài)鏈接庫dll文件的調(diào)用、代碼的實現(xiàn)與使用示例,非常實用,需要的朋友可以參考下
    2014-11-11
  • C#執(zhí)行SQL事務(wù)用法實例

    C#執(zhí)行SQL事務(wù)用法實例

    這篇文章主要介紹了C#執(zhí)行SQL事務(wù)用法,實例分析了通過C#中提供的Transaction執(zhí)行SQL事務(wù)的使用技巧,需要的朋友可以參考下
    2015-01-01
  • C#使用RestSharp實現(xiàn)封裝常用的http請求方法

    C#使用RestSharp實現(xiàn)封裝常用的http請求方法

    這篇文章主要為大家詳細介紹了C#如何使用RestSharp實現(xiàn)封裝常用的http請求方法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2024-02-02
  • C#如何實現(xiàn)dataGridView動態(tài)綁定數(shù)據(jù)

    C#如何實現(xiàn)dataGridView動態(tài)綁定數(shù)據(jù)

    這篇文章主要介紹了C#如何實現(xiàn)dataGridView動態(tài)綁定數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • C#讀取文件MD5值的實現(xiàn)代碼

    C#讀取文件MD5值的實現(xiàn)代碼

    這篇文章主要介紹了C#讀取文件MD5值的實現(xiàn)代碼,有了這個核心代碼,就可以實現(xiàn)校驗文件MD5值的一些程序了,需要的朋友可以參考下
    2014-08-08
  • C# 實現(xiàn)繪制PDF嵌套表格案例詳解

    C# 實現(xiàn)繪制PDF嵌套表格案例詳解

    嵌套表格,顧名思義,就是在一張表格中的特定單元格中再插入一個或者多個表格,本文將為大家介紹C#繪制PDF嵌套表格的代碼示例,需要的同學(xué)可以參考一下
    2021-11-11
  • Unity實現(xiàn)簡單虛擬搖桿

    Unity實現(xiàn)簡單虛擬搖桿

    這篇文章主要為大家詳細介紹了Unity實現(xiàn)簡單虛擬搖桿,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • Unity?UGUI的Dropdown下拉菜單組件使用詳解

    Unity?UGUI的Dropdown下拉菜單組件使用詳解

    這篇文章主要為大家介紹了Unity?UGUI的Dropdown下拉菜單組件使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • 簡單實現(xiàn)C#異步操作

    簡單實現(xiàn)C#異步操作

    這篇文章主要為大家詳細介紹了C#簡單實現(xiàn)異步操作的方法,通過BeginInvoke、EndInvoke的方式實現(xiàn)異步編程,感興趣的小伙伴們可以參考一下
    2016-02-02
  • c# webapi 配置swagger的方法

    c# webapi 配置swagger的方法

    這篇文章主要介紹了c# webapi 配置swagger的方法,文中示例代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07

最新評論