在运行时轻松替换dll

本文关键字:替换 dll 运行时 | 更新日期: 2023-09-27 17:53:50

我有一个基本的WinForm解决方案(MS VS2013, . net framework 4.5)用于测试Dll中包含的一些方法,使用反射。我的目标是测试主应用程序,它可以运行两个方法的Dll(不引用项目中的Dll),然后,运行四个方法(增加2个方法)不停止主应用程序,并再次运行,使用反射。

Reflections works fine(如果我停止主应用程序,替换dll文件并再次运行主应用程序,所有工作正常),但我无法在运行时替换dll。

主应用程序有一个定时器控制,间隔为60秒。每隔60秒,执行一个方法来检查DLL文件是否在文件夹中。如果该文件夹中存在一个DLL文件,我希望在主应用程序(正在运行)中使用新的DLL,因为新的DLL包含主应用程序需要的旧方法(第一个DLL)和其他方法。然而,我得到一个错误,文件正在使用中。

我已经阅读了几个帖子,问题,答案,MEF文档,AppDomains相关,但我一直无法连接信息,以便能够实现解决方案。

其实,在提出这个问题之前,我想了很多,但我承认,我宁愿花点时间羞愧,知道你可以帮助我。

如果你能帮我写代码和具体说明,那对我来说将是一个很大的帮助。

这是代码:

主要用途:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
namespace testDLLs
{
    public partial class Principal : Form
    {
        public Principal()
        {
            InitializeComponent();
        }
        private void Principal_Load(object sender, EventArgs e)
        {
            labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
            string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
            string[] aOperaciones = cListaOperaciones.Split('|');
            comboBoxOperaciones.Items.Clear();
            foreach (string cOperacion in aOperaciones)
            {
                comboBoxOperaciones.Items.Add(cOperacion);
            }
            timerForUpdate.Interval = 60000;
            timerForUpdate.Enabled = true;

        }
        private void buttonRun_Click(object sender, EventArgs e)
        {
            int iOperador1, iOperador2;
            string resultadoDesdeDll = null;
            string cOperacionSeleccionada;
            Int32.TryParse(textBoxOperador1.Text, out iOperador1);
            Int32.TryParse(textBoxOperador2.Text, out iOperador2);
            cOperacionSeleccionada = comboBoxOperaciones.GetItemText(comboBoxOperaciones.SelectedItem);
            object[] parametersArray = new object[] { iOperador1, iOperador2 };
            resultadoDesdeDll = metodosApoyo.RunDLLFunction(cOperacionSeleccionada, parametersArray);
            textBoxResultado.Text = resultadoDesdeDll;
        }
        private void timerForUpdate_Tick(object sender, EventArgs e)
        {
            labelUpdateStatus.Text = "Checking updates ...";
            notifyIconUpdate.Visible = true;
            notifyIconUpdate.BalloonTipText = "Instalando nuevo DLL....";
            notifyIconUpdate.BalloonTipTitle = "Info:";
            notifyIconUpdate.ShowBalloonTip(5000);
            if (File.Exists(@"C:'DLLsForCopy'OperacionesDLL.dll"))
            {
                File.Copy(@"C:'DLLsForCopy'OperacionesDLL.dll", @"D:'DLLs'OperacionesDLL.dll", true);
                labelVersionDll.Text = metodosApoyo.RunDLLFunction("VersionOperaciones");
                string cListaOperaciones = metodosApoyo.RunDLLFunction("ListaOperaciones");
                string[] aOperaciones = cListaOperaciones.Split('|');
                comboBoxOperaciones.Items.Clear();
                foreach (string cOperacion in aOperaciones)
                {
                    comboBoxOperaciones.Items.Add(cOperacion);
                }
            }
            labelUpdateStatus.Text = "";
            notifyIconUpdate.Visible = false;
        }
    }
}

项目中的类,对于主应用程序中的一些函数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace testDLLs
{
    class metodosApoyo
    {
        public static string RunDLLFunction(string cMetodo, object[] aParametros = null)
        {
            string cRetornoGlobal = "";
            Object resultado = null;
            string cOperacionSeleccionada = cMetodo;
            Assembly assembly = Assembly.LoadFile(@"D:'DLLs'OperacionesDLL.dll");
            Type type = assembly.GetType("OperacionesDLL.Operaciones");
            MethodInfo methodInfo = type.GetMethod(cOperacionSeleccionada);
            ParameterInfo[] parameters = methodInfo.GetParameters();
            object classInstance = Activator.CreateInstance(type, null);
            object[] parametersArray = null;
            if (aParametros != null)
            {
                parametersArray = new object[aParametros.Length];
                int i = 0;
                foreach (object value in aParametros)
                {
                    parametersArray[i] = aParametros[i];
                    i++;
                }
            }
            resultado = methodInfo.Invoke(methodInfo, parametersArray);
            cRetornoGlobal = (string)resultado;
            return cRetornoGlobal;
        }
    }
}

DLL源文件(operationesdll . DLL):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OperacionesDLL
{
    public class Operaciones
    {
        public static string VersionOperaciones()
        {
            string retorno;
            retorno = "1.0701-16";
            return retorno;
        }
        public static string ListaOperaciones()
        {
            string retorno;
            retorno = "Suma|Resta|Multiplicación|División";
            return retorno;
        }
        public static string Suma(int operador1, int operador2)
        {
            int resultado;
            string retorno;
            resultado = operador1 + operador2;
            retorno = resultado.ToString();
            return retorno;
        }
        public static string Resta(int operador1, int operador2)
        {
            int resultado;
            string retorno;
            resultado = operador1 - operador2;
            retorno = resultado.ToString();
            return retorno;
        }
        public static string Multiplicación(int operador1, int operador2)
        {
            int resultado;
            string retorno;
            resultado = operador1 * operador2;
            retorno = resultado.ToString();
            return retorno;
        }
        public static string División(int operador1, int operador2)
        {
            int resultado;
            string retorno;
            resultado = operador1 / operador2;
            retorno = resultado.ToString();
            return retorno;
        }
    }
}

在运行时轻松替换dll

您可以使用System.Addin命名空间中的Managed Addin Framework (MAF)来完成您所描述的操作。我曾经用它来编写扫描文件夹中的dll并动态加载它们的应用程序。您还可以使用它来卸载和重新加载dll,因为它们从文件夹中出现和消失。