开发者

Using two DLLs with same name and same namespace

开发者 https://www.devze.com 2023-01-31 03:46 出处:网络
I have a project which needs to reference two DLLs with the same name. The DLLs are not strong named, have the same exact name.

I have a project which needs to reference two DLLs with the same name. The DLLs are not strong named, have the same exact name.

I need to access some types within each DLL, but these types h开发者_如何学Pythonave the same fully qualified name. So let's say the first one is companyDLL.dll with someProduct.Type1 and the second one is companyDLL.dll with someProduct.Type1.

How can I access both Type1 classes within the same project?

I have already tried using extern alias, but it requires me to change the name of one of the DLLs.


If your two DLLs have the same name, you are going to have to rename them. Such as Assembly1.dll and Assembly2.dll.

Add these DLLs as a reference in your project as you normally would and in the properties for each reference specify an alias.

in your code when using the DLLs use extern alias to specify what dll you want to reference.

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

If you leave it like this, you will most likely get a FileNotFoundException saying that it Could not load file or assembly. To fix this you need to add a ResolveEventHandler that will load the correct assembly you are trying to use. To do this you have to specify exactly where you are storing your DLL files. In the case below, I manually copied the Dll files to the projects debug folder. Where it says "name of assembly1" you can find the name after you reference the DLL, build the project, and open the csproj file with notepad. What to look for will be below my example code.

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;
}

As promised, here is what a reference looks like in the csproj file. The name is everything inside the include attribute.

<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>

I know this is late but hopefully it will help anyone coming to this page from now on.


Using extern alias to bring the assemblies in with different namespaces. If you can differenciate the namespace, you should be able to use using altType1 = someProduct.Type1 to create a local alias for the type.

First qualify the assemblies from the command line:

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

Then reference them using extern alias:

extern alias productA;
extern alias productB;

Finally you can alias the local types:

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


I can think of two ways to handle this.

  1. load each DLL into a separate AppDomain. You'll have to make calls across the AppDomain boundary to tickle the various properties and methods.

  2. before loading the assemblies, disassemble and then re-assemble each assembly and put them into unique (maybe dynamically generated) namespaces. There are tools that can help with this (1) (2). You could potentially automate it.

But my base feeling is, you really shouldn't be doing this. It's easier to solve this problem upstream, than it is to solve it after you already have compiled assemblies.


None of the proposed solutions worked for me. I had to recompile the DLLs and give them different identity, i.e. change "Assembly name" in project settings.

If you are unable the recompile the DLLs, another solution would be to create wrappers with suitable names.


When I came across this problem I created two different wrapper projects, each referencing different version of the dlls, and used the Costura.Fody nuget in order to embed the dlls into the wrapper projects and prevent clashes in builds.

0

精彩评论

暂无评论...
验证码 换一张
取 消