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

在C#中如何獲取程序集

 更新時(shí)間:2024年03月16日 09:05:41   作者:錢行慕  
某一天我正在寫一些反射代碼,目的是遍歷所有的程序集來查找一個(gè)特定的接口,然后在Startup中調(diào)用其上的一個(gè)方法,這篇文章主要介紹了在C#中如何獲取程序集,需要的朋友可以參考下

某一天我正在寫一些反射代碼,目的是遍歷所有的程序集來查找一個(gè)特定的接口,然后在Startup中調(diào)用其上的一個(gè)方法??雌饋磉@個(gè)功能似乎很簡單,但是在現(xiàn)實(shí)中,卻沒有一個(gè)清晰的,簡單的,適合各種情形的方式來獲取一個(gè)程序集。這篇文章獲取對(duì)某些人來說非常的枯燥,但是如果我能夠幫助哪怕一個(gè)人來解決此類問題,那么這篇文章也是值得的。

說真的,由于有多種獲取程序集的方法,我將不會(huì)說”使用這個(gè)方法”。很有可能,對(duì)于你的特定的工程來說,也許只有一種方式可以工作,所以依賴其他的方式是毫無意義的。讓我們簡單的對(duì)所有的方式做個(gè)測(cè)試,然后看看哪一個(gè)方法是最合理的。

使用AppDomain.GetAssemblies

你可能會(huì)遇到的第一個(gè)選項(xiàng)是AppDomain.GetAssemblies。它(看似)加載了在AppDomain中的所有程序集,基本上可以說加載了你項(xiàng)目使用到的每一個(gè)程序集。但是卻存在著大量的警告。在.NET中程序集是延遲加載到AppDomain中的,它不可能一次性加載所有的程序集,而是等你調(diào)用了一個(gè)程序集中的方法/類的時(shí)候,它才會(huì)將它加載進(jìn)來--也就是即時(shí)加載。這是合理的,因?yàn)槿绻銖牟皇褂靡粋€(gè)程序集的話,是沒有理由加載它的。

但問題是在你調(diào)用AppDomain.GetAssemblies()的那個(gè)時(shí)間點(diǎn)上,如果你并沒有調(diào)用某個(gè)特定的程序集的方法,它便不會(huì)被加載?,F(xiàn)在如果你要為了Startup方法得到所有的程序集,很有可能你還沒有調(diào)用到那個(gè)程序集,這就意味著它還沒有加載到AppDomain,所以便獲取不到這個(gè)接口方法。

用代碼來說:

AppDomain.CurrentDomain.GetAssemblies(); // Does not return SomeAssembly as it hasn't been called yet.
SomeAssembly.SomeClass.SomeMethod();
AppDomain.CurrentDomain.GetAssemblies(); // Will now return SomeAssembly.

雖然這看起來是一個(gè)很有吸引力的選項(xiàng),但是要知道,對(duì)于這個(gè)方法來說,時(shí)機(jī)是一切。

使用AssemblyLoad事件

因?yàn)槟悴荒艽_保當(dāng)你調(diào)用CurrentDomain.GetAssemblies()時(shí)所有程序集都被加載了,而實(shí)際上當(dāng)AppDomain加載另一個(gè)程序集的時(shí)候有一個(gè)事件會(huì)運(yùn)行?;旧险f,當(dāng)一個(gè)程序集被延遲加載的時(shí)候,你可以被通知到。它看起來像是這樣:

AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
{
    var assembly = args.LoadedAssembly;
};

如果你只是想當(dāng)程序集加載的時(shí)候檢查下一些東西,那這或許是一個(gè)不錯(cuò)的解決方案,但是這個(gè)過程在某個(gè)特定的點(diǎn)并不是必然會(huì)發(fā)生(在你的.NET Core app的Startup.cs類中并不會(huì)發(fā)生)。

這個(gè)方法的另一個(gè)問題是到你添加你的事件處理器的那個(gè)時(shí)刻,并不能保證程序集還沒有被加載(事實(shí)上它們很可能已經(jīng)加載過了)。所以呢?你需要付出雙份的努力,首先添加你的事件處理器,之后迅速的檢查AppDomain.CurrentDomain.GetAssemblies,找到已經(jīng)被加載了的東西。

這是一個(gè)完美的解決方案,但是如果你習(xí)慣于使用延遲加載的程序集來做事的話,這就不能正常工作了。

使用 GetReferencedAssemblies()

排名中的下一個(gè)是GetReferencedAssemblies()。本質(zhì)上你可以通過一個(gè)程序集,比如你的入口點(diǎn)程序集,一般來說便是你的web項(xiàng)目,來得到所有引用的程序集。

其代碼本身看起來像是這樣:

Assembly.GetEntryAssembly().GetReferencedAssemblies();

再一次,看起來像是在玩把戲,但是這個(gè)方法有另一個(gè)很大的問題。在許多項(xiàng)目中會(huì)有一個(gè)“模式分離”的概念,比如 Web Project>>Service Project>>Data Project。Web Project本身并不直接引用Data Project。而當(dāng)你調(diào)用“GetReferencedAssemblies”時(shí)其意味著直接引用。因此如果你期望在程序集列表中得到Data Project,你將會(huì)失望不已。

所以,再一次的,在一些情況下可以正常工作,但并不是一個(gè)普遍的解決方案。

循環(huán)GetReferencedAssemblies()

使用GetReferencedAssemblies()的另一個(gè)選擇是創(chuàng)建一個(gè)方法來遍歷所有的程序集。類似于這樣:

public static List GetAssemblies()
{
    var returnAssemblies = new List();
    var loadedAssemblies = new HashSet();
    var assembliesToCheck = new Queue();
    assembliesToCheck.Enqueue(Assembly.GetEntryAssembly());
    while(assembliesToCheck.Any())
    {
        var assemblyToCheck = assembliesToCheck.Dequeue();
        foreach(var reference in assemblyToCheck.GetReferencedAssemblies())
        {
            if(!loadedAssemblies.Contains(reference.FullName))
            {
                var assembly = Assembly.Load(reference);
                assembliesToCheck.Enqueue(assembly);
                loadedAssemblies.Add(reference.FullName);
                returnAssemblies.Add(assembly);
            }
        }
    }
    return returnAssemblies;
}

這個(gè)方法的邊界處理得有點(diǎn)粗糙,但是它的確可以工作并且意味著在Startup方法中,你可以立即看到所有的程序集。

關(guān)于這個(gè)方法你可能會(huì)被卡住的一次是如果你正在動(dòng)態(tài)加載程序集,并且它們實(shí)際上并不會(huì)被任何項(xiàng)目所引用。對(duì)于這種情況,你需要下一個(gè)方法。

目錄DLL加載

一個(gè)很粗糙的獲取所有解決方案dll的方式是將它們加載出你的bin文件夾??雌饋硐袷沁@樣:

public static Assembly[] GetSolutionAssemblies()
{
    var assemblies = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
                        .Select(x => Assembly.Load(AssemblyName.GetAssemblyName(x)));
    return assemblies.ToArray();
}

它可以正常工作但的確是一個(gè)粗糙的解決方案。但是使用這個(gè)方式的一個(gè)最大的好處是一個(gè)dll只需要簡單的放置在需要加載的目錄中就可以。因此如果你出于任何原因動(dòng)態(tài)的加載DLLs,對(duì)于你來說,這很可能是唯一的方法(除過在AppDomain中監(jiān)聽AssemblyLoad)。

這是做這件事情的看起來像惡作劇的方式之一。但是很可能你已經(jīng)被阻擋到角落之中而這正是解決問題的唯一方式。

僅僅得到“我的”程序集

使用這些方法中的任何一種,您會(huì)很快發(fā)現(xiàn)你正在將Nuget下的每個(gè)程序集加載到你的項(xiàng)目中,包括Nuget包、.NET核心庫甚至運(yùn)行時(shí)特定的dll。在.NET世界中,程序集就是程序集。沒有“是的,但這是我的程序集”并且它們很特別的概念。

過濾的唯一方法就是檢查名字。您可以將其作為白名單來執(zhí)行,因此如果解決方案中的所有項(xiàng)目都以“MySolution”開頭。因而你可以像這樣來進(jìn)行過濾:

Assembly.GetEntryAssembly().GetReferencedAssemblies().Where(x => x.Name.StartsWith("MySolution."))

或者你可以選擇一個(gè)黑名單選項(xiàng),這個(gè)選項(xiàng)并不真正限制你的程序集,但至少可以減少你正在加載/檢查/處理的程序集的數(shù)量。就像這樣:

Assembly.GetEntryAssembly().GetReferencedAssemblies()
.Where(x => !x.Name.StartsWith("Microsoft.") && !x.Name.StartsWith("System."))

黑名單可能看起來很蠢,但在某些情況下,如果您正在構(gòu)建一個(gè)實(shí)際上不知道最終解決方案名稱的庫,那么這是減少您試圖加載的內(nèi)容的唯一方法。

到此這篇關(guān)于在C#中如何獲取程序集的文章就介紹到這了,更多相關(guān)C#獲取程序集內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c#實(shí)現(xiàn)無標(biāo)題欄窗口的拖動(dòng)

    c#實(shí)現(xiàn)無標(biāo)題欄窗口的拖動(dòng)

    本篇文章是對(duì)c#中實(shí)現(xiàn)無標(biāo)題欄窗口拖動(dòng)的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 實(shí)例代碼講解c# 線程(下)

    實(shí)例代碼講解c# 線程(下)

    這篇文章主要介紹了c# 線程的的相關(guān)資料,文中示例代碼非常細(xì)致,對(duì)大家的學(xué)習(xí)有很大幫助,感興趣的朋友可以了解下
    2020-06-06
  • c#獲取gridview的值代碼分享

    c#獲取gridview的值代碼分享

    這篇文章主要介紹了C#如何在事件中獲得GridView里面TextBox的值,大家參考使用吧
    2013-12-12
  • c#入門之循環(huán)語句使用詳解(for循環(huán)、do/while)

    c#入門之循環(huán)語句使用詳解(for循環(huán)、do/while)

    這篇文章主要介紹了c#入門之循環(huán)語句使用詳解,有for循環(huán)和do/while的示例,需要的朋友可以參考下
    2014-04-04
  • C#調(diào)用exe文件的方法詳解

    C#調(diào)用exe文件的方法詳解

    這篇文章主要為大家詳細(xì)介紹了C#調(diào)用exe文件的相關(guān)方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2024-04-04
  • C#實(shí)現(xiàn)拼圖游戲

    C#實(shí)現(xiàn)拼圖游戲

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)拼圖游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C#實(shí)現(xiàn)DataTable數(shù)據(jù)行列轉(zhuǎn)換

    C#實(shí)現(xiàn)DataTable數(shù)據(jù)行列轉(zhuǎn)換

    這篇文章介紹了C#實(shí)現(xiàn)DataTable數(shù)據(jù)行列轉(zhuǎn)換的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#進(jìn)度軸控件分享

    C#進(jìn)度軸控件分享

    這里給大家介紹的是使用C#實(shí)現(xiàn)的進(jìn)度軸的方法和示例,非常的實(shí)用,有需要的小伙伴可以參考下。
    2015-06-06
  • 淺談C#中的值類型和引用類型

    淺談C#中的值類型和引用類型

    在C#中值類型的變量直接存儲(chǔ)數(shù)據(jù),而引用類型的變量持有的是數(shù)據(jù)的引用,數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)堆中。下面我們來簡單談?wù)凜#中的值類型和引用類型
    2016-06-06
  • Unity使用ScrollRect制作搖桿

    Unity使用ScrollRect制作搖桿

    這篇文章主要為大家詳細(xì)介紹了Unity使用ScrollRect制作搖桿,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04

最新評(píng)論

辽阳市| 札达县| 穆棱市| 苗栗县| 富平县| 高要市| 墨竹工卡县| 吉木萨尔县| 湾仔区| 吉首市| 敦煌市| 梓潼县| 芮城县| 盘山县| 洞口县| 攀枝花市| 金华市| 苏州市| 淮北市| 惠水县| 保康县| 弋阳县| 洪洞县| 康定县| 定结县| 凤台县| 内江市| 铜山县| 罗甸县| 章丘市| 苏尼特右旗| 麦盖提县| 安溪县| 江油市| 桓台县| 买车| 墨玉县| 泽州县| 崇仁县| 濮阳市| 瓦房店市|