2010-12-14 189 views
10

我有一個需要引用兩個具有相同名稱的DLL的項目。這些DLL名稱不是很強,具有相同的確切名稱。使用兩個具有相同名稱和相同名稱空間的DLL

我需要訪問每個DLL中的某些類型,但這些類型具有相同的完全限定名稱。 因此,可以說是DLL1 companyDLL.dll - > someProduct.Type1 DLL 2是companyDLL.dll - > someProduct.Type1

我怎麼能在同一個項目中同時訪問 '類型1'?

我已經嘗試過使用'extern alias',但它需要我更改其中一個DLL的名稱。

請讓我知道,如果我的問題需要進一步澄清。

+8

這完全屬於「如果你試圖做到這一點,你的設計被嚴重破壞」。 – cdhowie 2010-12-14 23:09:07

+0

絕對同意,這是一個需要來自公司產品(使用.NET構建)的兩個版本的信息的工具。但是這裏所討論的產品是受到管制的,因此不能改變。 – varosh 2010-12-15 18:55:20

回答

0

我可以想出兩種方法來處理這個問題。

  1. 將每個DLL加載到單獨的AppDomain中。你將不得不通過AppDomain邊界進行調用來剔除各種屬性和方法。

  2. 在加載程序集之前,反彙編然後重新組裝每個程序集並將它們放入唯一的(可能是動態生成的)名稱空間中。有些工具可以幫助解決這個問題(1)(2)。您可以將其自動化。

但我的基本感覺是,你真的不應該這樣做。在上游解決這個問題比在已經編譯程序集之後解決它更容易。

+0

Cecil可能比ildasm更好,因爲您可以直接使用C#操作IL。 – cdhowie 2010-12-14 23:46:06

+0

對於上面的#1:如何添加對同一個項目中具有相同名稱的兩個DLL的引用? – varosh 2010-12-15 18:56:46

3

使用extern alias將程序集帶入不同的命名空間。如果您可以區分命名空間,則應該可以使用using altType1 = someProduct.Type1爲該類型創建本地別名。

首先在命令行資格的組件:

/r:ProductA=companyDLLA.dll 
/r:ProductB=companyDLLB.dll 

使用extern alias然後參考他們:

extern alias productA; 
extern alias productB; 

最後,你可以別名當地類型:

using productTypeA = productA.Type1; 
using productTypeB = productB.Type1; 
+0

對我來說不幸的是,這兩個dll具有相同的名稱.i.e./r:ProductA=companyDLLA.dll /r:ProductB=companyDLLA.dll – varosh 2010-12-15 18:55:51

+0

是否有一個原因,您不能重命名該DLL?如果我處於您的情況,我會嘗試將它們重命名爲'companyDLLv1.dll'和companyDLLv2.dll'。 – 2010-12-15 21:09:38

+0

是的,DLL不能被重命名。這裏所討論的DLLs是受到規範的,如果沒有經過官方的批准程序(這對我的場景來說是不可能的) – varosh 2010-12-16 02:22:45

11

如果您兩個DLL具有相同的名稱,您將不得不重命名它們。如Assembly1.dll和Assembly2.dll。

將這些DLL作爲參考添加到項目中,就像您通常會在每個參考的屬性中指定一個別名一樣。

在您的代碼中使用DLL時使用extern alias來指定您要引用的dll。

extern alias Assembly1Reference; 
using Assembly1Reference::AssemblyNamespace.MyClass; 

如果你離開它這樣,你將最有可能得到一個FileNotFoundException說,它無法加載文件或程序集。要解決這個問題,你需要添加一個ResolveEventHandler,它會加載你正在使用的正確的程序集。要做到這一點,你必須指定你的DLL文件的存儲位置。在下面的情況下,我手動將Dll文件複製到項目調試文件夾。在說到「assembly1名稱」的地方,你可以在引用DLL之後找到名稱,構建項目並用記事本打開csproj文件。要查找的內容將在我的示例代碼下面。

extern alias Assembly1Reference; 
extern alias Assembly2Reference; 

static void Load() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 
    Do(); 
} 

static void Do() 
{ 
    new Assembly1Reference.Assembly.Class(); 
    new Assembly2Reference.Assembly.Class(); 
} 

static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    string currentPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 
    if(args.Name == "Name of assembly1")//Found in csproj file after referenced and built 
    { 
     return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly1.dll")); 
    } 
    if(args.Name == "Name of assembly2")//Found in csproj file after referenced and built 
    { 
     return System.Reflection.Assembly.LoadFile(System.IO.Path.Combine(currentPath, "Assembly2.dll")); 
    } 
    return null; 
} 

如所承諾的,這是參考在csproj文件中的樣子。名稱是include屬性中的所有內容。

<Reference Include="MyAssembly_3.6.2.0, Version=3.6.2.0, Culture=neutral, PublicKeyToken=12341234asdafs43, processorArchitecture=MSIL"> 
     <SpecificVersion>False</SpecificVersion> 
     <HintPath>Resources\Assembly1.dll</HintPath> 
     <Aliases>Assembly1Reference</Aliases> 
</Reference> 

我知道這是晚了,但希望它能幫助任何人從現在開始到此頁面。

+0

這是有用的,我可以使這部分工作,但我有以下問題。這樣做的目的是什麼? 'static void Do(){new Assembly1Reference.Assembly.Class();新的Assembly2Reference.Assembly.Class(); }還有什麼是通過代碼解析程序集的優勢,而不是像[this]那樣通過app.config(https://stackoverflow.com/a/3163050/431561)。在我的情況下,總是最新版本的程序集正在加載。我該怎麼做才能加載特定的重命名程序集的確切dll。 – Rajaraman 2018-02-20 12:45:07