未收到 MVVM Light Messenger 和动态 Dll 消息

MVVM Light Messenger and Dynamic Dll Messages not received

我正在开发一个 WPF 项目,我们在其中使用 MVVM Light Messenger 和 SimpleIOC。该解决方案有几个项目提供了使用串行/USB 设备的实现,这些实现使用一个公共接口来抽象出各种设备的细节。

在应用程序启动时,解决方案会在 IOC 中注册我们的依赖项:

Kernel.Container.Register<IMainWindow, MainWindow>(Lifestyle.Transient);
//more dependency registrations.

MainWindow加载时,我们检测用户想要使用哪个设备并加载它。但是,因为我们不想将应用程序与设备实现紧密耦合,所以 WPF 应用程序中没有对任何设备实现的直接引用。加载设备时,我们使用Reflection拉入DLL并构造对象,并传回公共接口IDevice.

加载DLL和构建设备的代码:

public static Assembly GetAssembly(string dll)
{
            var codeBase = Assembly.GetExecutingAssembly().CodeBase;
            var uri = new UriBuilder(codeBase);
            var path = Uri.UnescapeDataString(uri.Path);
            //Load the assembly from the specified path.
            var theDirectory = Path.GetDirectoryName(path);
            var strTempAssmbPath = string.Format(@"{0}\Devices\{1}", theDirectory, dll);
            var theDll = Assembly.LoadFile(strTempAssmbPath);
            return theDll;
}

//Actual code that gets the assembly and loads the IDevice
var assembly = GetAssembly("MyDevice.dll");
(IDevice)Activator.CreateInstance(assembly.GetType(type), ConstructorConstraint);

每个设备都使用静态 MessageBus(对我们的消息传递库的直接项目引用)在设备上发生事件时将消息发送回应用程序(同样,允许从 WPF 应用程序中抽象出设备实现)。这是我们的 MessageBus 实现:

public static class MessageBus
    {
        public static void Send<T>(T message)
        {
            Messenger.Default.Send(message);
        }

        public static void Receive<T>(object subscriber, Action<T> action) where T : MessageBase
        {
            Messenger.Default.Register(subscriber, action);
        }
    }

当通过调试器 运行 运行应用程序时,一切都很好,一切都按预期工作。然而,在通过我们的构建过程构建我们的应用程序并打包安装程序,然后在我们的 QA 机器上安装之后,WPF 应用程序将 运行 像正常一样,适当地加载设备,但设备实现发送的消息没有被运行ning 应用程序中的 MainWindow 收到。

我们现在的 运行ning 理论是,因为设备是在 运行 时间加载的,所以它们没有获得对 Messaging 库的相同引用(Messaging DLL 是丢失或设备 dll 中的引用与 WPF 应用程序中的引用不同)。我们正在尝试将 Messaging DLL 复制到 Devices 文件夹中并获得一些混合结果。

为什么在我们构建和打包应用程序以供发布后,设备发送的消息没有被我们的应用程序接收,但它在调试器中运行?

解决方案非常难以捉摸,并没有真正解释行为,但我们能够解决问题。

基本上,我们的构建过程使用 ILMerge 的开源版本,它将依赖项合并到输出可执行文件中。作为该过程的一部分,ILMerge 版本在将程序集合并到 WPF 可执行文件中时存在问题,这些可执行文件不是 WPF 项目本身的嵌入式资源。要解决该问题,我们必须在嵌入所有引用的 WPF 项目上执行 MSBuild 任务,以便 ILMerge 进程可以正确合并它们。此处的示例:https://gist.github.com/thoemmi/3724333

事情开始变得有点奇怪了。容纳我们 MessageBusMessaging 项目是 WPF 项目中的直接引用,并且正在通过我们的构建过程嵌入和合并。我们的设备 DLL 无法从构建输出中解析合并到程序集中的那些引用。

为了让事情正常进行,我们修改了构建过程以将 Messaging DLL 输出到与应用程序可执行文件相同的目录中,一切都按预期进行。

这不是我们所希望的优雅解决方案,但它确实解决了我们的问题。

如果有人想出更好的答案来解决问题,我很乐意测试一下并将其作为答案。