C# 程序集別名


C# 程序集別名

1. extern alias

雖然開發項目時很少遇到兩個相同完全限定名的類型(命名空間.類名),但偶然還是會遇到這種情況。比如,在某些情況下,項目中必須引用某程序集的新舊多個版本。 通過使用外部程序集別名,可以將來自每個程序集的命名空間包裝在由別名命名的根級別命名空間中,從而使這些命名空間可以在同一文件中使用。

MSDN官方解釋:

You might have to reference two versions of assemblies that have the same fully-qualified type names. For example, you might have to use two or more versions of an assembly in the same application. By using an external assembly alias, the namespaces from each assembly can be wrapped inside root-level namespaces named by the alias, which enables them to be used in the same file.

注意這和單獨extern 關鍵字來使用非托管代碼(C++d等)不是一回事。

要引用兩個具有相同完全限定類型名的程序集, 例如:

extern alias GridV1;

extern alias GridV2;

每一個外部別名聲明都引入一個額外的根級別命名空間,它與全局命名空間global平行,而不是在全局命名空間內。 因此,通過使用根源於相應命名空間別名的完全限定名,可以無歧義地引用每個程序集的類型。在程序中,GridV1::Grid 是來自 grid.dll 的網格控件,而 GridV2::Grid 是來自 grid20.dll 的網格控件。

如下圖所示,一般所有程序集的別名都默認是global,將別名修改為其它名稱就可以extern alias 方式使用了。extern alias 一般需要寫在所有using 程序集名語句之前。

extern alias V2;
using System;

Visual Studio中可以給一個程序集起多個別名,用逗號隔開,所以下圖中屬性名顯示的是Aliases而不是Alias。

2. 實際測試

新建一個解決方案,包括三個項目: 2個有相同命名空間的類庫項目,1個控制台測試項目。

 

ClassLibraryV1項目中Cat類和Puppy類如下:

using System;

namespace ClassLibrary
{
    public class Cat
    {
        public void Meow()
        {
            Console.WriteLine("A cat meow1.");
        }
    }
}
using System;

namespace ClassLibrary
{
    public class Puppy
    {
        public void Bark()
        {
            Console.WriteLine("A puppy bark.");
        }
    }
}

ClassLibraryV2項目中Cat類和Puppy類如下:

using System;

namespace ClassLibrary
{
    public class Cat
    {
        public void Meow()
        {
            Console.WriteLine("A cat meow2.");
        }
    }
}
using System;

namespace ClassLibrary
{
    public class Dog
    {
        public void Bark()
        {
            Console.WriteLine("A dog bark.");
        }
    }
}

然后TestLibrary項目引用ClassLibraryV1和ClassLibraryV2。

1)測試只使用完全限定名不同的類

static void Main(string[] args)
 {
        var puppy=new  ClassLibrary.Puppy();
        puppy.Bark();

         var dog=new ClassLibrary.Dog();
         dog.Bark();

         Console.ReadKey();
}

運行正常(這種情況是最普通的,雖然程序集的命名空間相同,但是類型不同)

2)測試使用完全限定名相同的類

首先,編譯器會報錯:無法判斷有歧義的類型。

這時,就需要更改程序集別名,如將ClassLibraryV1的別名從global改為V1,

extern alias V1;
using System;

namespace TestLibrary
{
    class Program
    {
        static void Main(string[] args)
        {
            var cat1 = new V1::ClassLibrary.Cat();
            cat1.Meow();
            var cat2 = new ClassLibrary.Cat();
            cat2.Meow();

            var puppy = new V1::ClassLibrary.Puppy();
            puppy.Bark();
            var dog=new ClassLibrary.Dog();
            dog.Bark();

            Console.ReadKey();
        }
    }
}

運行結果:

3. 項目擴展感悟

遇到一個改造程序,程序中大部分開發的代碼引用的是一家控件廠商的最新版本(V15)。但是,程序引用的一個A.dll是基於V13開發的(即A.dll用到了V13的某個類型)。首先,如果不引用V13到程序中,則編譯不通過(提示找不到某類型);然后引用V13后,也編譯報錯(很多類型存在歧義)。

最后解決方式是把V13的程序集別名改為非global(任意名都可以),程序中也沒有地方需要用extern alias,編譯成功后運行正常。

為什么沒有用到extern alias?

猜測是因為該程序開發中並沒有直接用到V13的類型,只是引用的A.dll用到了V13; 程序運行時自身用到的V15程序集正常加載,A.dll也加載入內存,A.dll加載時根據其CLR manifest描述來加載V13程序集。具體機制還需要深入學習下CLR等相關知識。

轉載請注明出處:https://www.cnblogs.com/lichu-lc/p/12863586.html

參考:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extern-alias


免責聲明!

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



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