如何从资源中的 DLL 调用函数?

How do I call functions from a DLL in my resources?

所以我有这个 DLL 和另一个我认为被称为注入器/加载器的东西?它基本上将我的 DLL 加载到它自己的进程中,因此它将我的 DLL 加载到 "Injector.exe" 的进程中 在下面的示例中,它不是从资源中加载,而是从桌面加载,这里同样适用。

现在正在加载它,它实际上并没有调用任何函数,这就是我的问题所在。

我想在加载 DLL 时调用一些 Messagebox 函数。

据我所知,最合乎逻辑的方法是在 btnAssemblyLoad_Click 事件中执行此操作,因此当事件发生时,它会调用 DLL 中的函数。 问题是我不知道这会叫什么,我读了一些关于 "Reflection" 但我不确定这是我需要的东西。

我该如何处理?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AssemblyLoader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if(ofd.ShowDialog() == DialogResult.OK)
            {
                tbAssemblyLocation.Text = ofd.FileName;
            }
        }

        private void btnAssemblyLoad_Click(object sender, EventArgs e)
        {

            AssemblyName an = AssemblyName.GetAssemblyName(tbAssemblyLocation.Text);
            Assembly.Load(an);
        }
    }
}

DLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MSgBOxDllCS
{
    public class Funcs
    {
        public void CallMessageBox()
        {
            MessageBox.Show("Hello");

        }
    }
}

您需要调用非静态 class 的实例方法,见下文。

// Step 1: load assembly to memory
var an = AssemblyName.GetAssemblyName(tbAssemblyLocation.Text);
var assembly = Assembly.Load(an);

// Step 2: get type from the assembly by name
var type = assembly.GetType("MSgBOxDllCS.Funcs");

// Step 3: get method of the type
var method = type.GetMethod("CallMessageBox");

// Step 4: create instance of the type
var funcs = Activator.CreateInstance(type);

// Step 5: invoke the instance method
method.Invoke(funcs, null);

一般来说,您正在构建的称为插件框架,互联网上有大量示例说明如何完成,您也可以根据需要利用现有框架。

您可以通过多种方式实现这一目标。

  1. 加载一个程序集,创建一个 class 的实例,使用反射找到所需的方法并调用它。
var assembly = Assembly.LoadFrom(DllFilePath);
var funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
var method = funcs.GetType().GetMethod("CallMessageBox");
method.Invoke(funcs, null);
  1. 相同但使用动态对象,减少对反射成员的控制但看起来更好:
var assembly = Assembly.LoadFrom(DllFilePath);
dynamic funcs = assembly.CreateInstance("MSgBOxDllCS.Funcs");
funcs.CallMessageBox();
  1. 最后但并非最不重要的一点是,提取接口并将其放入单独的共享 DLL 中。这种方法将有助于摆脱反射调用,并且就其本质而言是最可靠的:

常用共享 DLL:

namespace Shared
{
   public interface IFuncs
   {
      void CallMessageBox();
   }
}

要加载的DLL:

namespace MSgBOxDllCS
{
    public class Funcs : Shared.IFuncs
    {
        public void CallMessageBox()
        {
            MessageBox.Show("Hello");
        }
    }
}

加载器:

var assembly = Assembly.LoadFrom(DllFilePath);
var funcs = (Shared.IFuncs)assembly.CreateInstance("MSgBOxDllCS.Funcs");
funcs.CallMessageBox();