DotNet友元程序集解析


   項目開發的過程中,調試使用的可能是最多的操作。任何代碼寫出來都需要經過調試和整合,以此擴展和提升程序的穩定性和可靠性。談到.NET的單元測試,在這里就得提提.NET的友元程序集這一特性,也借用.NET進行單元測試的一個較為好用的.NET屬性,來講解一下程序集、定制Attribute的相關知識。一些知識需要反復的去品味和反思,不要覺得你會了就不在意,等你在意的時候,你就有些力不從心的意思了。

   生活在於不停的折騰,只有經過磨練,才可知何時需要安分,何時需要挑戰。

   毒雞湯喝完了,來聊聊正事...

一.程序集概述

  本文主要是談論“友元程序集”的一些知識,既然是做一個解析,那么就應該把一些知識做一個展開來論述。在這里先談談程序集(有人覺得很了解,有人覺得完全不懂,情況不同,選擇不同,需者自取吧),接下來我們具體的看看程序集這一特性。

  程序集是一個或多個模塊/資源文件的邏輯分組,程序集是重用、安全性以及版本控制的最小單元。對於程序集的結構有如下圖。

    對於程序集的組成就不一一做解析,在這里就單獨談談元數據這一結構。元數據是一個二進制數據塊,由一組數據表,元數據總是與包含IL代碼的文件關聯,元數據由幾個表構成。元數據的作用有上圖介紹。元數據的表有三個類別:定義表,引用表,清單表。對於這些表的結構在這里就不做介紹了,有興趣的可以搜索一下,個人認為元數據這一結構應該好好的研究一下。

二.定制Attribute概述

   上面的論述中簡單的介紹了程序集的結構和元數據,在這里簡單的介紹一下定制Attribute這一.NET的特性。定制Attribute允許定義的信息應用於幾乎每一個元數據表記錄項,這種可擴展的元數據信息能在運行時查詢,從而動態改變代碼的執行方式。在C#種,為了將一個定制Attribute應用於一個目標元素,需要將Attribute放置於目標元素前面的一對方括號中。

   CLR允許將定制Attribute應用於可在文件的元數據中表示的幾乎所有元素。定制Attribute主要應用於程序集、模塊、類型、字段、方法、方法參數、方法返回值、屬性、事件、泛型類型參數。attribute是類的一個實例,將一個attribute應用於一個目標元素時,語法類似於調用類的某個實例構造函數。定制Attribute的實例如下:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true, Inherited = false)]

    上面代碼取自InternalsVisibleToAttribute類中,該類是完成友元程序集特性的核心對象,下面會做一個具體的介紹。AttributeUsage需要接受一個AttributeTargets枚舉類型的值作為參數,稱之為定位參數,是強制性的,必須指定。AllowMultiple參數用於獲取或設置一個布爾值,指示是否有多個實例指定的屬性可以為單個程序元素指定。Inherited參數用於獲取或設置一個布爾值,指示指定的屬性是否可以繼承由派生類和重寫成員。

   定制Attribute可以應用於單個目標元素,定制Attribute的順序是無關緊要的。在C#種,可將每個Attribute都封閉到一對方括號中,也可以在一對方括號中封閉多個以逗號分隔的Attribute。

   定制Attribute就是一個類的實例,它被序列化成駐留在元數據中的一個字節流,在運行時,可以對元數據中包含的字節進行反序列化,從而構造類的一個實例。

三.友元程序集解析

   扯了半天,終於到講解“友元程序集”這一個概念,“友元程序集”在.NET2中提出,使用InternalsVisibleToAttribute來實現這一特性,InternalsVisibleTo只能用於程序集,並且你可以在同一個程序集種應用多次。源程序集:包含這個屬性的程序集。友元程序集能夠看到源程序集的所有內部成員,類似於公有的。

   友元程序集實例介紹:

//AssemblySource.DLL
[assembly: InternalsVisibleTo(DotNetShare)]
public class AssemblySource
{
    public static void Share();
}


//DotNetShare.DLL
public class DotNetShare
{
    private static void Main()
    {
        AssemblySource.Share();
    }
}

    AssemblySource.DLL和DotNetShare.DLL之間存在一種特殊的關系,但是這種關系只能單項操作。接下來看一下InternalsVisibleToAttribute的實現源碼。InternalsVisibleToAttribute繼承自Attribute類,該類指定通常僅在當前程序集中可見的類型對指定程序集可見。該類包含兩個屬性和一個方法。

   1.AssemblyName

public string AssemblyName
    {
      [__DynamicallyInvokable] get
      {
        return this._assemblyName;
      }
    }

   該屬性為一個只讀屬性,一個表示友元程序集名稱的字符串。該屬性用於獲取友元程序集的名稱,采用 internal 關鍵字標記的所有類型和類型成員對該程序集均為可見。

  2.InternalsVisibleToAttribute()

public InternalsVisibleToAttribute(string assemblyName)
    {
      this._assemblyName = assemblyName;
    }

   該方法為一個構造函數,用指定的友元程序集的名稱初始化 <see cref="T:System.Runtime.CompilerServices.InternalsVisibleToAttribute"/> 類的新實例。接收一個友元程序集的名稱。

  對於友元程序集有一個約束,如果一個友元程序集是簽名的,那么源程序集為了保證信任正確的代碼,就需要指定友元程序集的公鑰。

四.總結

   對於本文主要是在介紹友元程序集這一特性,順帶介紹程序集和定制Attribute這兩個特性,方便大家理解友元程序集這一特性。這篇文章希望對大家有所幫助,還是那句話,需者自取,也虛心接受吐槽。知識在於分享,更在於每一個人的思考。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM