我正在构建一个使用非常简单的插件系统的程序。这是我用来加载可能的插件的代码:
public interface IPlugin
{
string Name { get; }
string Description { get; }
bool Execute(System.Windows.Forms.IWin32Window parent);
}
private void loadPlugins()
{
int idx = 0;
string[] pluginFolders = getPluginFolders();
Array.ForEach(pluginFolders, folder =>
{
string[] pluginFiles = getPluginFiles(folder);
Array.ForEach(pluginFiles, file =>
{
try
{
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(file);
Array.ForEach(assembly.GetTypes(), type =>
{
if(type.GetInterface("PluginExecutor.IPlugin") != null)
{
IPlugin plugin = assembly.CreateInstance(type.ToString()) as IPlugin;
if(plugin != null)
lista.Add(new PluginItem(plugin.Name, plugin.Description, file, plugin));
}
});
}
catch(Exception) { }
});
});
}
当用户从列表中选择特定插件时,我启动插件的Execute方法。到现在为止还挺好!正如您所看到的,插件是从文件夹加载的,并且在该文件夹中有几个dll是需要的插件。我的问题是我无法让插件“看到”dll,它只是搜索启动的应用程序启动文件夹,而不是搜索加载插件的文件夹。
我尝试了几种方法: 1.将当前目录更改为plugins文件夹。 2.使用对SetDllDirectory的操作间调用 3.在注册表中添加一个条目以指向我希望它看的文件夹(参见下面的代码)
这些方法都不起作用。我错过了什么?当我动态加载dll插件时,它似乎不遵守任何上述方法。我还能尝试什么?
此致 MartinH。
//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
Microsoft.Win32.RegistryKey appPaths = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(
string.Format(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\{0}",
System.IO.Path.GetFileName(Application.ExecutablePath)),
Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree);
appPaths.SetValue(string.Empty, Application.ExecutablePath);
object path = appPaths.GetValue("Path");
if(path == null)
appPaths.SetValue("Path", System.IO.Path.GetDirectoryName(pluginItem.FileName));
else
{
string strPath = string.Format("{0};{1}", path, System.IO.Path.GetDirectoryName(pluginItem.FileName));
appPaths.SetValue("Path", strPath);
}
appPaths.Flush();
答案 0 :(得分:2)
使用Assembly.LoadFrom
而不是Assembly.LoadFile
答案 1 :(得分:2)
每当我动态加载这样的插件时,我通常会创建一个app域并在新的app域中加载程序集。创建应用程序域时,可以指定基目录。将从此基本目录加载从属程序集。