C# 使用包含动态加载dll本身的动态加载dll
简介 我的程序允许其他开发人员编写插件。这些插件(是dll文件)放在某个目录中,我的程序可以在运行时这样加载它们:C# 使用包含动态加载dll本身的动态加载dll,c#,dynamic,dll,plugins,C#,Dynamic,Dll,Plugins,简介 我的程序允许其他开发人员编写插件。这些插件(是dll文件)放在某个目录中,我的程序可以在运行时这样加载它们: Assembly assembly = Assembly.LoadFrom("MyPluginPath"); object Plugin = assembly.CreateInstance("Plugins.Main", true); 然后程序将能够通过以下方式从插件调用main方法: var pluginType = Plugin.GetType(); var methodOu
Assembly assembly = Assembly.LoadFrom("MyPluginPath");
object Plugin = assembly.CreateInstance("Plugins.Main", true);
然后程序将能够通过以下方式从插件调用main
方法:
var pluginType = Plugin.GetType();
var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param});
这适用于我迄今为止编写的所有遵循以下特定结构的插件:
namespace Plugins
{
public class Main : IDisposable
{
public Bitmap MyInternalMethod(Bitmap param)
{
// method body
}
}
}
问题
现在我要编写一个新插件,它在运行时本身加载一个外部dll:
namespace Plugins
{
public class Main : IDisposable
{
[System.Runtime.InteropServices.DllImport("MyExternalDLL.dll")]
unsafe private static extern int Initialize(int* arg1, char* arg2);
public Bitmap MyInternalMethod(Bitmap param)
{
// method body
Initialize(x,y);
}
}
}
Initialize(x,y)
方法在上面的代码中给出了一个错误
未能初始化com库
注释
Func
对象传递给我的插件,但是Func
不允许指针变量(Initialize
方法包含int*
和char*
等参数),即使它允许,我不确定这个解决方案是否有效winApi
,正如下面的回答中所建议的“Sinatr”,但错误仍然存在。我甚至尝试使用winApi
在主程序中加载myexternaldl.dll
,并将检索到的Initialize
方法的地址传递给我的插件,就像下面的代码一样,但错误保持不变(这样错误发生在func(x,y)
):接口
是不可能的甚至可以像我描述的那样使用包含动态加载dll的动态加载dll吗?如果是的话,我应该怎么做才能让它工作?只是出于好奇,为什么不使用MEF?@SébastienSevrin我从来没有听说过,我现在正在检查它,但是我的主程序有点大,它已经使用了很多插件。如果我要使用MEF,我是否必须更改应用程序的许多主要部分?您可以尝试使用winapi在插件本身中动态加载
myexternaldl.dll
,请参见答案。你必须提供plugin init/deinit方法,加载DLL。你必须在你的主应用程序中为你的插件映射添加一些代码,并在你的插件中添加一些属性,所以是的,会有一些变化,这可能是主要的。这是一个有点离题,所以让我给你一个很好的例子,如果你想尝试它。祝你好运。@SébastienSevrin,谢谢你的回复和链接。
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string name);
IntPtr dllHandle = IntPtr.Zero;
IntPtr addr = IntPtr.Zero;
private void RunPlugin()
{
dllHandle = LoadLibrary("MyExternalDLL.dll");
addr = GetProcAddress(dllHandle, "Initialize");
var methodOutput = pluginType.GetMethod("MyInternalMethod").Invoke(Plugin, new object[] {param, addr});
}
public class Main : IDisposable
{
private unsafe delegate byte initialize_api(int* arg1, char* arg2);
public Bitmap MyInternalMethod(Bitmap param, IntPtr addr)
{
// method body
//initialize_api is a delegate with the same signature as Initialize(x,y);
var func = (initialize_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(initialize_api));
func(x,y);
}
}