4

I am working on an app that will load plug-ins. The plug-in assemblies reside in a directory that is below my app's main directory.

Looks like this:

MyAppFolder
----------->ThePluginFolder
----------------Assembly1
----------------Dependency1

My problem occurs with Dependency1 (this is an assembly that Assembly 1 references). The CLR fails to find it.

I have done some reading on Fusion, and it looks as though I could correct this by setting a Private Path with currentAppDomain.AppendPrivatePath.

However, in the .NET 4.0 help, they say that this method is obsolete. They point me to the AppDomainSetup, but I can't use that to modify my current app domain.
Does anyone know what else I can do to get these dependencies to load?

Options I've considered:

  1. I could manually loop through Assembly1's references, and if I find an assembly in the plug-in folder, I could manually load it. (seems like my best option, but I want to make sure I'm not missing anything)

  2. I could hook the AssemblyResolve event of my current domain (but this even looks weird -- you return a value. Does that imply that it's not multicast? I'm handling one aspect of plug-in (a business rule), what if another part of my app wanted plug-in reports? Would I need 1 global event handler?

dtb
  • 213,145
  • 36
  • 401
  • 431
JMarsch
  • 21,484
  • 15
  • 77
  • 125

3 Answers3

2

Thanks for all the help, guys. In my case, I found that the best thing to do was to locate the plugins in my main application directory. Although I could ues Load() or LoadFrom() to load the assemblies in separate dirs (and it would appear to work), I later ran into serializtion problems (the referred to assembly had classes that need to be serialized and deserialized).

I tried using LoadFrom() and Load(), supplying various evidence in the AssmblyName parameter. I even "manually" loading the assemblies that were referenced by my plug-ins. No amount of dynamic loading would make deserialization work (I got exceptions).

I only found 3 ways to have my dynamically loaded plug-ins work with serialization:

  1. Use CurrentDomain.AppendPrivatePath to add a path to the directory that had my assemblies (this method is obsolete)

  2. Hook the ResolveAssembly event in the current AppDomain (this would have worked, but it gets called alot, and I don't want to impact my application's performance -- note that I haven't taken measurements, though).

  3. Just put the assemblies in my main directory. (this was the simplest solution, and the only argument against doing so was that the directory structure was not as tidy as my other options. So, all things considered. I took this route.

JMarsch
  • 21,484
  • 15
  • 77
  • 125
  • FWIW, you (or other future visitors) might also be interested in my attempt to solve the problem outlined in [this question and its answers](http://stackoverflow.com/questions/10923727/plugin-appdomains-workaround). – O. R. Mapper Nov 27 '13 at 12:57
1

Plugin assemblies are usually loaded through reflection using Assembly.LoadFrom and should not be referenced by your project, otherwise they are hard-coded. The only common thing between the application and the plugin should be a separate assembly containing interfaces that both reference. Then you could have a configuration file in which you specify plugins to be loaded at runtime.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    @Darin: My project doesn't reference the plugin. (I'm using Assembly.LoadFromFile to load it). What's going on is that My project is dynamically loading a plugin. The plugin, in turn, references an assembly. that secondary assembly that is being referenced by the plugin is the one that isn't loading. – JMarsch Feb 10 '10 at 17:30
  • @JMarsch: according to the documentation: `The load-from context allows an assembly to be loaded from a path not included in probing, and yet allows dependencies on that path to be found and loaded because the path information is maintained by the context.` – Darin Dimitrov Feb 10 '10 at 17:33
  • Interesting. I'll give that a try -- Maybe I should have chosen LoadFrom instead of LoadFile. – JMarsch Feb 10 '10 at 17:36
  • @JMarsch, yes, you should use LoadFrom. Here's what LoadFile documentation says: `Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does.` – Darin Dimitrov Feb 10 '10 at 17:42
1

This scenario works for me, my plugin directly is totally separate to my application directory (its a web app), and dynamically loaded DLLs find their referenced DLLs in the same folder. Their refernced DLLs are also loaded as plugins by my application though, so it does know of their existence...

cjk
  • 45,739
  • 9
  • 81
  • 112
  • Yah, that's my option 1 -- make the calling app load the dependencies manually. Thanks -- you've added some validation to that plan of attack. – JMarsch Feb 10 '10 at 17:34