Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用包含动态加载dll本身的动态加载dll_C#_Dynamic_Dll_Plugins - Fatal编程技术网

C# 使用包含动态加载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

简介

我的程序允许其他开发人员编写插件。这些插件(是dll文件)放在某个目录中,我的程序可以在运行时这样加载它们:

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库

注释

  • 我为我的插件创建了一个可执行的测试应用程序,它工作得很好,所以我知道在运行时将其用作dll时会出现问题
  • 我想也许我应该在主程序中加载我的外部dll,然后将它作为
    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);
            }
        }