问题
I've been trying to crack this one over the last couple of weeks and have not found a good solution yet; hopefully I can get an answer here.
I have two assemblies (ZA & ZB), both of which point to a common project/dll (ZC) but which could be on a different version (i.e. same dll name, same namespaces, some classes may be different). Each assembly works by itself, however, if one is loaded by the other at runtime (e.g. A loads B), then I cannot get it to work. Need some help.
Here's the setup:
- ZA depends on ZC (common) version 1.1
- ZB depends on ZC version 1.0
ZA needs to load needs to load something in ZB (which depends on ZC), at runtime.
ZA is the master app.
Under its bin
directory, there's a plugins directory plugins/plugin-ZB
under which I would like to place all of ZB and its dependencies (ZC).
Here's what I've tried so far:
Assembly.Load()
using same version of dll - worked fine.
Assembly.Load()
using different versions of dll - ZB loads, but when the method runs, I get a method not found exception.
AppDomain.Load()
got a file not found error; I even used the delegate to resolve assemblies.
Some details regarding ZC:
- some methods are public static (some are not). E.g. Log.Log("hello");
- some may return values (primitives or objects).
- some methods are non static (and return values).
Help? - TIA
回答1:
m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll"))
m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll"))
Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString)
Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString)
m_OldObject = m_Assembly1.CreateInstance("FullClassName")
m_NewObject = m_Assembly2.CreateInstance("FullClassName")
From here on out I used late binding and/or reflection to run my tests.
.NET: Load two version of the same DLL
回答2:
Apart from Jonathan Allen excellent advice, a more "classical" way to resolve the problem is by loading the 2 versions in 2 different AppDomanis. You can then use .NET Remoting to make the two AppDomains comunicate. So ZA should create a new Appdomain, Load in this AppDomain ZB and invoke some operation in ZB via Remoting.
Note that .NET Remoting has some requirements on the classes that you want to use (inheritance from MarshalByRef), and creating an AppDomain is an expensive operation.
Hope this help
回答3:
I have had two versions of the same assembly loaded at the same time. It happened with a scenario just as you describe it.
You have to convince the runtime to load the same version of ZC for both ZA and ZB. I have found two ways to do that:
- Use a
bindingRedirect
element in your App.config file. There are some details in this question. - Use the
AppDomain.AssemblyResolve
event. There are some details in this answer.
The only problem with AppDomain.AssemblyResolve
is that it only triggers when the runtime can't find the requested version. If both versions are available, then you'll have to use the bindingRedirect
. I have used the AppDomain.AssemblyResolve
event and then added a safety check that makes sure the right version was loaded by looking through the assembly's referenced assemblies collection. If it isn't, I complain to the user that an old version of the library is lying around and tell them where it is.
来源:https://stackoverflow.com/questions/1189372/loading-2-versions-of-assembly-at-runtime