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

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.

Related

Assembly or file not found on plugin system C#

I have a project that uses plugins based on an interface, they are coded in other "Class Library" projects in the same main project solution. The main project has a folder that contains all the plugins in dll format. So for example I have a Plugins folder in "Bin/Debug/". All the plugins are compiled on that directory.
Each plugin project has a reference to the main project as it uses the main framework (reference not copied locally).
Each plugin should be able to use methods from other plugins, here I have the problem.
Example:
I have PluginA and PluginB, 2 DLLs, 2 different projects but the DLLs are in the same Plugins folder.
Now I want to instantiate PluginB in PluginA class so I add a reference to PluginB DLL (not copied locally). No errors from the Compiler.
But when I istantiate PluginA on the main project after loading all the plugins assemblies, I get a System.IO.FileNotFoundException Assembly or file not found. (referred to PluginB)
Basically seems that when I call a Plugin, from the main project, that calls another Plugin, I get an error. I've also tried to use the Assembly Resolve event without success.
Maybe I made some mistakes with the entire plugins system, it's the first time I use them.
Sorry for my english, I'm italian.
Thanks for the help.

MEF with extra DLLs

I have an Outlook plugin created that uses MEF to load extensions. The extensions are all created as C# class libraries. When the Outlook plugin starts, it copies all the plugin DLLs from a network directory to the local computer and then loads them via MEF.
For one of them, I'm using the MySql.Data.dll library. That dll is copied to the same directory where I place the DLL's which MEF loads in, but that one isn't working. The end user gets an exception saying it can't find that MySql dll.
What's the trick to placing extra DLLs that are needed by a class library included via an MEF import?
I haven't used MEF in a project but I have had to roll my own plug-in architecture on a couple of occassions. Something you can try is hooking in to the AppDomain.AssemblyResolve event. I don't know how useful the example is on that page but you could examine the assembly name in the event args and attempt to load that assembly from the same folder you are loading the plug-ins from.

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.

how to use dll of same name but different version from different locations in same application?

We are trying to program a couple of plugins for another application. We have two directories each with the code it needs to run independently whcih contain all the dll's (but not the exe as its 3rd party and we have no control over it). There is some shared code in a dll, placed in each plugin directory. When introducing a new version of the plugin we need to change this shared dll in one of the plugin directories but leave the other. When we do this the old version breaks as it relies on the older version of the shared dll but it only loads one. Is there a way to force it to use a certain version of the dll?
you should use the latebinding approach System.Reflection

How to deploy multiple programs referencing one DLL?

We have many projects using interop & related DLL. All projects have individual DLL reference with setup, but basically all of them use same DLL. So that's creates problem many times if any DLL register/unregister while installation/unistallation of setup.
Also, above approach can create problem if setup location changed or DLL reference location changed.
We need to place DLL at one location and all projects require to use DLL reference from that location to avoid register/unregister problem. But wondering about how actual reference located in .net for dependencies.
How can we do that? Any better solution or workaround for that?
Personally I like to make all my applications include all the DLLs referenced for a couple of reasons:
I can do a clean install and uninstall to remove all traces of my application without worrying about breaking anything
If I make a change to the shared DLL i don't have to worry about breaking other applications
But if you really need one location, you can register the DLL in the Global assembly cache. If you use a deployment tool like Wix this is pretty straightforward. Alternatively you could use a custom action to do the registration in the GAC
Put the assembly/interop dll into the Global Assembly Cache (GAC).
References:
How to deploy unmanaged dll into GAC
http://blogs.msdn.com/yizhang/archive/2007/06/17/how-to-deploy-unmanaged-dll-into-gac.aspx
Global Assembly Cache
http://msdn.microsoft.com/en-us/library/yf1d93sz.aspx
Use Merge modules: Merge modules provide a standard method by which developers deliver shared Windows Installer components and setup logic to their application. ...
This link might be helpful or just google for "visual studio setup project merge module".

Categories