Loading different version assemblies, what dependency assemblies will be loaded? - c#

I am writing an app that will use different versions of assemblies and call their methods. Question is, what dependency assemblies will they use.
For example :
AbcV1.dll has dependency assembly General.dll, both files located
in \App\V1
AbcV2.dll has dependency assembly General.dll, both
files located in \App\V2
Application also has dependency assembly General.dll, located with executable.
Lets assume General.dll is also not same in all folders, its changed too.
Now, when application will load AbcV1.dll and AbcV2.dll by reflection. Will they use their own General.dll or they will use Application's General.dll ?

Related

.net Runtime doesn't probe plugin folder

We have a .net plugin for an application that does not load a dependent library from the plugin folder.
Scenario:
Application (Revit.exe in program files) -> Loads plugin from c:\programdata\revit\plugindir\ourplugindir\<plugin.dll+dependencies>
On most machines, the load works fine. For the context of the issue, the dll dependencies are as follows
Revit.exe loads plugin.dll (revit.exe is in programfiles, plugins are in a separate predefined directory under programdata)
plugin.dll loads IdentityModel.dll (in ourplugindir directory)
IdentityModel.dll loads System.Text.Encodings.Web.DLL (in ourplugindir)
Successful probing looks like this:
IdentityModel requires System.Text.Encodings.Web.DLL
Initiate probing
Check GAC (fail)
Check root folder where Revit.exe is present (fail)
Check private sub folders where Revit.ext is present (fail)
Check ourplugindir (success)
On the machine where the plugin load fails, for some reason it does not probe ourplugindir and is hence unable to find System.Text.Encodings.Web.DLL.
The plugin dll is built using .net 4.7. The dependency is an indirect dependency.
From MSDN: https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
Assembly location can also be determined using the current binding
context. This most often occurs when the Assembly.LoadFrom method is
used and in COM interop scenarios. If an assembly uses the LoadFrom
method to reference another assembly, the calling assembly's location
is considered to be a hint about where to find the referenced
assembly.
Since the plugins are dynamically loaded by Revit.exe, I can only assume that the application uses Assembly.LoadFrom or something similar to load the plugins.
So the question is, why does the runtime correctly probe and find the dependent dll in the plugin folder on some machines while it doesn't probe the same folder on other machines?
Have you tried using an assembly resolver?

Plugin architecture in C# with external dll like Open.XML from Nuget

I have created a plugin architecture in C# app. In special folder I upload dlls and system search for certain interface and using reflection invokes function within plugin. But one of plugins (dlls) references to Open.XML dll which is not installed on the server where app is running. Is it a way to create a plugin ( compile it ?) that contains all libraries that it needs. Or it should be done in a different way?
1) Distribute any required DLLs together with the plugin DLL, and put them inside the plugin folder. Either add the plugin folder to the probing path for assemblies in the app.config, or add a handler for the AssemblyResolve event.
2) Use ILMerge to combine the plugin and required assemblies into one assembly.
If you load all plugins into the same app domain, this will cause funny issues if the same types are merged into multiple plugins.

C# IoC Container that scans the bin folder

I am looking for an IoC container that scans all types in all assemblies within the bin folder AND is compatible with mono.
I used to use LightCore, which took a little configuration to declare the implementation of a specific interface, and then automagically resolves it, but it doesn't seem to be compatible with mono...
I have tried TinyIoC too, but that one only scans types within referenced assemblies, and my problem is that the assembly that contains the implementation cannot be referenced by my other project that needs to resolve it (circular reference issue).
Thanks!

Why does the assembly reference gets loaded successfully when using MEF?

Contrary to the usual issues of MEF users, I'm not trying to figure out why a dependency of an assembly I load with MEF is not resolved. I am solving the opposite problem - trying to find out why the dependency is loaded.
The situation is that I have an ASP.NET application which uses MEF to dynamically load extension assemblies residing outside the application directory. There may be several versions of the same extension assembly in different directories I probe with MEF, each with its own set of dependencies and these dependencies again may be multiple versions of a single assembly (i.e. extension A.dll, 1.0.0.0 has a dependency D.dll, 1.0.0.0 and an extension B.dll, 2.0.0.0 has a dependency D.dll, 2.0.0.0).
It works in a sense that all the extensions and all their dependencies are loaded correctly. And I don't know why. I have no special settings in my web.config file. Where in the official documentation on assembly resolving does it say that it should work? It doesn't say anything about looking at the same directory the requesting assembly is located at.
I was hoping the Fusion Log Viewer would tell me how the runtime locates the dependencies but even though it shows me the binding requests for all the different versions of a given dependency, when I click on it to see the full log, I only see failed bindings (and yes, I have it set to log all binding requests, not just the failed ones).
Can anyone point me to the part of an official documentation explaining why this scenario works?
The main resolution with MEF is determined by the ComposablePartCatalog used. For example, if you use DirectoryCatalog, all assemblies within the specified directory get probed and found.
By looking at the CompositionContainer, you should be able to find the catalogs that are in place, which in turn should provide some details as to why the parts are composing properly.
It is also possible that your dependencies are being found due to the rules defined in "Other Locations Probed":
If an assembly uses the LoadFrom method to reference another assembly, the calling assembly's location is considered to be a hint about where to find the referenced assembly. If a match is found, that assembly is loaded.
If you are using a DirectoryCatalog to find the assemblies within a directory, it internally loads every assembly within that folder. This will cause all of your dependencies to also be loaded into the process when the DirectoryCatalog is constructed.

MEF Different Assembly Version Loading Issue

I have a bit of a conundrum with MEF.
I have an installer and configuration application shell which uses MEF to load individual installer components. This gives an end user the ability to select from whatever components have been placed into the install distributable.
The first install components which were written to use this used version 11 of SQLServer SMO libraries. Installing against either 2008R2 or 2012 works fine. (lets call this component A)
I have another team migrating code to a new component but that code uses version 10 of the SQLServer SMO, RMO, and SSIS (DTS) libraries. (lets call this component B)
When MEF goes to load component B I get a LoaderExceptionFailure for one of the SQLServer DLLs (Microsoft.SqlServer.Replication). It actually gives a FileNotFoundException (listing the DLL). The DLL exists in the component's directory. It is the correct version 10.
The shell application already has version 11 files in it.
Is there a way I can tell the application context what to do? Is there a way I can tell the component to load any specific libraries it needs?
I want to assume that each component can specify something "Associated.Library, Version=1.0.0.0, publickey=abcdef123456789, culture=none".
The reason the CLR (not MEF) cannot find the assembly is because it is neither in the GAC, not in the places were the current AppDomain is setup to probe for assemblies.
One way to deal with this kind of problem is to add the missing assembly to the GAC.
Another approach is to add the folder containing the missing assembly to the probing paths of your application. If you don't mind deploying these assemblies in the application base folder (the one containing your executable) then do so. Otherwise you can add deploy it in a sub folder of your application base folder and add the folder to the privatePath element of your app.config.
You will find more information on the article: How the Runtime Locates Assemblies.

Categories