1

So imagine the scenario, A.dll and B.dll, A.dll references B.dll and calls methods that reside within B.dll.

At some point in the future you have two different versions of A.dll and B.dll (it's not important why this is the case). You want to be able to use both versions of these dll's from within the same application.

The problem I've encountered is that I can load Av1.dll, and Av2.dll but they both end up using Bv1.dll.

So what I want is:

Av1.dll --> Bv1.dll
Av2.dll --> Bv2.dll

But as I say what I end up with is:

Av1.dll --> Bv1.dll
Av2.dll --> Bv1.dll

AppDomains aren't really viable as they end up being unwieldy due to every input and output needing to implement MarshalByRefObject.

I'm open to creative solutions even if they are a tad outlandish. This is more of an academic question so don't get bogged down with just refactoring the dll's or some fudge that you'd need to do in the real world, treat it as a challenge.

Is it possible? Like could you dynamically inspect, re-write and recompile the dll's behind the scenes but replacing the references to give, in effect:

A.dll --> B.dll
C.dll --> D.dll

As I say, I'm open to creative solutions.

Edit

Ok so maybe a clearer example would help.

Let's imagine a 3rd party has provided you with library to calculate income tax. This library consists of dll's that reference each other.

So under normal circumstances you'd have:

TaxHelper helper = new TaxHelper();
var result = helper.CalculateIncomeTax(...params...);

But let's imagine that for the following tax year your 3rd party provides you with a new version of the library, because the rules have changed in the new tax year, but you also must be able to calculate tax for the previous years. All they have done is change the code and recompiled, all the class and dll names are all the same.

So what I've been experimenting with is something along these lines (this is just off the top of my head btw so might not be 100% right):

Assembly taxHelper1Assembly = Assembly.LoadFrom(...path1...);
Assembly taxHelper2Assembly = Assembly.LoadFrom(...path2...);

Type taxHelper1Type = taxHelper1Assembly.GetType(...);
Type taxHelper2Type = taxHelper2Assembly.GetType(...);

dynamic taxHelper1 = Activator.CreateInstance(taxHelper1Type);
dynamic taxHelper2 = Activator.CreateInstance(taxHelper2Type);

var result1 = taxHelper1.CalculateIncomeTax(...params...);
var result2 = taxHelper2.CalculateIncomeTax(...params...);

Now this works, up to a point, taxHelper1 and taxHelper2 are both different versions and will return different results...however...although the top level TaxHelper classes are different, internally where they reference other dll's as dependencies, taxHelper1 references the correct dependencies because they were loaded first, taxHelper2 ALSO references taxHelper1 dependencies.

Edit 2

Think I've found the answer in this thread: Loading Dependent Assemblies Manually

David
  • 1,731
  • 24
  • 37
  • 1
    I think [DependencyInjection](https://msdn.microsoft.com/en-us/library/hh323705(v=vs.100).aspx) can solve this. – raidensan May 18 '18 at 11:18
  • Please provide a [MCVE] so we know what you're thinking/doing exactly, then we might be able to help re-engineer your approach. – rory.ap May 18 '18 at 11:20
  • I assume the DLL's can not be modified, or better to say, recompiled in requested state from source codes. This would be simple *(change namespace and rename files)*. A few moths *(or year(s)?)* I saw here on stackoverflow a way, how to use Two classes with the same name, in same namespace from two different DLL's. This would be a way. Place old and new DLL in different folders. The another way would be to use **cecil** *(or similar tools)* to change the DLL in binary/compiled form and use the updated version. – Julo May 18 '18 at 11:52
  • Julo, yes DLL's can not be modified, they are essentially black boxes without decompiling. I can get to the point to of creating two different versions of top level classes from different dll's, my issue is that internally the 2nd instance references the wrong dependencies. – David May 18 '18 at 12:53
  • @raidensan - The problem arises from different DLL versions not from different implementations. – martinstoeckli May 18 '18 at 15:06

1 Answers1

0

Here, this might be enough to get you started. It's called dependency injection, as someone mentioned in the comments under your question. You should read about it.

Here I define two types in my A.dll. One of them is an interface which defines a contract for B:

public interface IDependencyB
{
    string Name { get; }
}

And here's my A class. It takes an IDependencyB in its constructor:

public class A
{
    public A(IDependencyB dependencyB)
    {
        System.Diagnostics.Debug.Print(dependencyB.Name);
    }
}

Then you can define two (or however many) variations of classes, in separate assemblies if you wish, that implement that interface:

class B1 : IDependencyB
{
    public string Name => "B1";
}

class B2 : IDependencyB
{
    public string Name => "B2";
}

You can test it like so:

var b1 = new B1();
var b2 = new B2();
var a1 = new A(b1);
var a2 = new A(b2);

It's a pretty basic example, but it should set you in the right direction, I think.

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • Hi rory.ap thanks for replying, I've updated my original post with a better example of what I'm looking to do. – David May 18 '18 at 12:44
  • The problem arises from different DLL versions not from different implementations. DotNet is very touchy about loading DLLs with a wrong version number. – martinstoeckli May 18 '18 at 15:05