Using two DLLs with same name and same namespace
Asked Answered
A

5

16

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

Angio answered 14/12, 2010 at 23:5 Comment(3)
This falls squarely into the category of "if you're trying to do this, your design is severely broken."Wanting
Definitely agreed, this is for a tool which needs information from two versions of a company product (built with .NET). But the product in question here is regulated and hence can't be changed.Angio
@Wanting Not necessarily. There is a wide range of different scenarios involving a conversion between old and new versions, or for example benchmark comparisons.Photocell
S
12

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.

Stieglitz answered 18/3, 2014 at 17:0 Comment(1)
This is useful and I could make this work this partially but I have following questions. What is the purpose of this? static void Do() { new Assembly1Reference.Assembly.Class(); new Assembly2Reference.Assembly.Class(); } Also what is the advantage of resolving the assemblies via code rather than via app.config like this. In my case, always the latest version of the assembly is getting loaded. What should I do to load the exact dll of the particular renamed assembly.Ferrite
P
3

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;
Pacha answered 14/12, 2010 at 23:16 Comment(3)
unfortunately for me, the two dlls have the same name.i.e./r:ProductA=companyDLLA.dll /r:ProductB=companyDLLA.dllAngio
is there a reason you cannot rename the DLL? If I were in your situation, I would attempt renaming them companyDLLv1.dll and companyDLLv2.dll`.Pacha
Yes, the DLLs cannot be renamed. The DLLs in question here are regulated and cannot be changed without going through an official approval process (which is out of question for my scenario)Angio
P
1

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.

Photocell answered 29/8, 2018 at 11:28 Comment(0)
R
1

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.

Rhettrhetta answered 24/2, 2020 at 21:8 Comment(0)
S
0

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.

Supernumerary answered 14/12, 2010 at 23:15 Comment(2)
Cecil may be a better approach than ildasm, as you can manipulate the IL directly using C#.Wanting
For #1 above: how can i add a reference to two DLLs with the same name in the same project?Angio

© 2022 - 2024 — McMap. All rights reserved.