I'm trying to make application with plugins.
I have MainLib.dll, where I made some commnon interface(let it be ICommon
) with 1 method. Then, I made 2 .dlls(plugins) which have reference to MainLib.dll and implement the ICommon
in some classes. Also, I removed all the references in this .dlls exept System
.
Then, I created an application, which monitors folder ".\\Plugins"
and loads all .dlls in newDomain
, check if the types in .dll implement ICommon
(so this application also reference to MainLib.dll). If yes - add the name of .dll in some list.
And now here the problem: before I tried to load plugins - I load MailLib.dll and System to newDomain because all plugins have dependency of this .dlls. They load correct. Then, I start to load plugins, and here I have:
FileNotFoundException, Could not load file or assembly 'PluginWithException, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.) on string Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName);
PluginWithException assembly has only 2 dependency - System and MainLib. Before I tryied to load PluginWithException I checked assemblies in new domain, System and MainLib were loaded to this domain. So I can't see any ploblems with dependency. I read this topic, and tryed the solution with ProxyDomain
but the exception is the same.
What I'm doing wrong?
Here the code:
public static List<string> SearchPlugins(string[] names)
{
AppDomain domain = AppDomain.CreateDomain("tmpDomain");
domain.Load(Assembly.LoadFrom(@".\MainLib.dll").FullName);
domain.Load(@"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
MessageBox.Show(GetAssembies(domain)); // here I can see that System and MailLib exist in new domain
List<string> plugins = new List<string>();
foreach (string asm in names)
{
Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName); // here I have exception
var theClassTypes = from t in loadedAssembly.GetTypes()
where t.IsClass &&
(t.GetInterface("ICommonInterface") != null)
select t;
if (theClassTypes.Count() > 0)
{
plugins.Add(asm);
}
}
AppDomain.Unload(domain);
return plugins;
}
you don't specify how you're setting up your search paths for your AppDomains so that it can find the DLLs in the Plugins directory, however your problem sounds like it might be very similar to this one I answered yesterday:
AppDomain.Load() fails with FileNotFoundException
Perhaps this also will resolve your issue? Let me know how you get on.
You may want to tell the domain where to load your assemblies from:
AppDomain domain = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins") });
However, I don't see why you are loading assemblies in current (default) domain and also the tmpDomain.