在运行时轻松替换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;
}
}
}
您可以使用System.Addin
命名空间中的Managed Addin Framework (MAF)来完成您所描述的操作。我曾经用它来编写扫描文件夹中的dll并动态加载它们的应用程序。您还可以使用它来卸载和重新加载dll,因为它们从文件夹中出现和消失。