1

I am at the beginning of designing a system to be deployed across a job site, your boring, dime-a-dozen, database server backend multi-client system.

One feature that I am very keen to implement in this system is the ability for a development team to making running changes with requiring a client reboot. I'm not so much worried about UI changes, those can require a reboot, but functional changes in behavior.

Currently I've started a basic layout using C# with WPF UI's, using an MVVM architecture, and making full use of PRISM and Dependency Injection.

I've thought of two approaches currently:

  1. Plugin based system using the MEF frame work. So far in my prototyping, I been able to define default behavior, and then provide alternative behaviors depending on what dll is loaded.

  2. Some sort of scripting support, be it LUA or trying the Roslyn based C# scripting. I've not researched this one as thoroughly yet, but it seems like it can work, but only if careful consideration is given to what tools are exposed to the scripts

Pros of approach 1: seems to work fine in small scale prototype, and gives a the most control very easily

Cons of approach 1: in my testing once a object is loaded in MEF, it can't be unloaded except be unloading the whole application domain, and passing objects between domains is...a process to say the least.

Pros of approach 2: Deployment would be very easy, and CSIX would be easy to write in existing tools. LUA would not be much different. From my (VERY limited) testing, there would be no problem with reloading the script from disk before each execution to ensure that the most recent one is ran. and This shouldn't cause any great performance hit, as a script should only be executed at the absolute most, once a minute, but more likely, once an hour.

Cons of approach 2: Least amount of development has been put into this so far. The surface of what is available has to be explicitly declared, and or else a change in requirements would result in a recompile and re-release any way. From what I can tell, the most limited in functionality so far.

So what approach would result in the most easy to modify system?

Also are there any pitfalls I missed with either approach?

Is there an Option 3 that I haven't considered yet?

1 Answer 1

1

MEF is good for large pieces, such as implementing a plugin architecture. It's benefit is for when you have functionality you only want available to certain users. For example, added functionality that a group has paid for; or a plugin for accounting that doesn't exist for HR. It is designed to dynamically load and connect pieces at start-up time. It is not meant for dynamic unload and reload.

The biggest issue you need to think about is your deployment mechanism. You won't be able to get around requiring users to stop the app and restart it. It's the question of how you intend to make those updates available. You have several options:

  • Super low tech: App code lives on a file share, and only the loader is installed on the desktop. The loader finds the directory for the currently deployed version, and simply calls it.
    • Pro: super easy to upgrade everyone just by dropping the new app in a new directory
    • Con: you have to be really good about protecting that fileshare from bad actors
  • Microsoft One-Click: Don't try it. It was supposed to be a means of downloading a current version of the app and running it on demand, but the sandbox constraints typically don't play nice with DI and MEF based applications
    • Pro: if you can make it work, you only need a webserver to host the app, no admin privileges required
    • Con: it changes your runtime context, so a lot of things break
  • Microsoft Software Center: not a bad solution if your enterprise is all on Windows 10. This allows the enterprise to push updates to each desktop where your application is installed.
    • Pro: if your enterprise already supports this, it is one of the more secure and better managed ways of pushing updates to users
    • Con: if you need to support more than Windows 10 users, it won't work
  • Side-car updater app: Basically, this is the same solution that Visual Studio and Office 365 uses. The updater app can download and install updates on demand, and the application checks a server for the current version.
    • Pro: you have full control over the update process. If the update is to the user's local profile, then no admin privileges are required.
    • Con: it's another app to develop and maintain, along with the server side support.

In your situation, you have to think about what is feasible for your enterprise. That will require some conversations with the people who run the enterprise. The side-car updater app will only really work if the user has the permissions to install things on their system. Software Center does not, but it's only feasible if your enterprise is using it.

I hate to say it, but sometimes the super-low tech solution just fits the bill. You can build your launcher as a script or as a tiny C# application. It works, it's unsophisticated, and there's some administrative magic you need to handle. It sounds like your "option 2" solution.

3
  • Every single one of those examples completely ignores the most important requirement. I need to make running changes, no restarts allowed
    – Whistler
    Jan 13, 2020 at 16:44
  • Then you are most likely going to have to explore the world of application domains. You can't unload classes that are already read in, but you can discard and recreate app domains and everything loaded inside. Without doing that, you run the risk of conflicting class loading. Jan 16, 2020 at 13:35
  • You can absolutely load an assembly at runtime. You just can't unload it. That's why App Domains exist. They are going to be a pain in the butt. Jan 16, 2020 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.