在运行时更换DLL而不会感到痛苦

时间:2016-07-01 21:56:03

标签: c# .net dll system.reflection

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

思考工作正常(如果我停止主应用程序,替换dll文件并再次运行主应用程序,一切正常),但我无法在运行时替换dll。

主应用程序有一个间隔为60秒的Timer控件。每隔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源码(OperacionesDLL.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;
        }
    }
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

您可以使用System.Addin命名空间中的Managed Addin Framework(MAF)执行您要描述的内容。我已经用它来编写扫描文件夹中的DLL并动态加载它们的应用程序。您还可以使用它来卸载和重新加载DLL,因为它们出现并从文件夹中消失。