I'm working on a WPF project where we are using MVVM Light Messenger and SimpleIOC. The solution has several projects that provide implementations for working with Serial / USB devices, and those implementations use a common interface to abstract away the details of the various devices.
At application startup, the solution registers our dependencies in the IOC:
Kernel.Container.Register<IMainWindow, MainWindow>(Lifestyle.Transient);
//more dependency registrations.
When MainWindow loads, we detect which device the user wants to use and load it up. However, because we don't want to tightly couple the application to the device implementations, there are no direct references in the WPF application to any of the Device implementations. When loading a device, we use Reflection to pull in the DLL and construct the object, and pass back the common interface IDevice.
Code for loading the DLL and constructing the device:
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);
Each device uses a static MessageBus (direct project reference to our Messaging library) to send messages back to the application when events on the device happen (again, allowing device implementations to be abstracted away from the WPF application). Here is our MessageBus implementation:
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);
}
}
This is all well and good when running the application through the debugger, and everything works as expected. However, after building our application through our build process and packaging the installer, then installing on our QA machines, the WPF application will run like normal, load the device appropriately, but the messages that the device implementation sends are not being received by the MainWindow in the running application.
The running theory we have right now is that because the devices are being loaded at runtime, they are not getting the same reference to the Messaging library (either the Messaging DLL is missing or the reference in the device dll is not the same as the reference in the WPF application). We are experimenting with copying out the Messaging DLL into the Devices folder and getting some mixed results.
Why aren't the messages that the devices send being received by our application after we build and package the application for release, but it works in the debugger?