Reputation: 29834
We are new to the .NET world and have built a small C# application on top of Nancy
We are looking for a way to "package" the application code so that we can programmatically hot deploy and undeploy it on top of a minimal Nancy based container (or any other appropriate container you may suggest)
How do we do this in the .NET world ?
In the JVM world, one way to do it is to package a Web Application Resource (war) that is deployed on top of a servlet engine, typically Jetty or Tomcat. There are other solutions (micro-containers, using class loaders directly, etc..). We are looking of an equivalent .NET paradigm.
EDIT Dec 5
There seems to be solutions around building Assemblies and using methods such as Assembly.LoadFromString.
This still seems pretty manual and we are looking for a C# library/framework to help with loading/unloading
Upvotes: 0
Views: 517
Reputation: 261
Unfortunately, it's not a typical task in .NET world, so you won't necessarily find a simple widely used plug-ins solution.
There is Managed Extensibility Framework, later known as Microsoft.Composition, later known as System.Composition. Please check How to discover new MEF parts while the application is running? as it may be a solution you are looking for.
There are some articles on using System.Composition with .NET Core as well.
It's not hard to implement a plugin system yourself though using an IoC framework like AutoFac .
Let's assume your application has Nancy modules which do call services, and the services implement the actual logic you may want to change dynamically. That makes a service essentially a plugin. The idea is to make IoC to return an updated instance of a service for every http call.
Sadly, in both cases you will have to manually detect an assembly file changed, but this is a trivial job with FileSystemWatcher class.
Also, in some IoC libraries updating dependencies in runtime is not considered a good practice, take a look here, for example.
Upvotes: 1
Reputation: 101523
You can load your code into separate AppDomain
and use shadow copying for hot reload. Suppose you have nancy application like this:
static void Main(string[] args) {
using (var host = new NancyHost(new Uri("http://localhost:34455"))) {
host.Start();
Console.WriteLine("started");
Console.ReadKey();
}
}
public class SampleModule : Nancy.NancyModule {
public SampleModule() {
Get["/"] = _ => "Hello World!";
}
}
And you want to be able to update it without restarting hosting process. You can do it like this (warning - non-production ready code, just sample). Create another application like this:
static void Main() {
while (true) {
var setup = new AppDomainSetup();
setup.ApplicationBase = @"Path to directory with your nancy app";
setup.ShadowCopyFiles = "true";
var domain = AppDomain.CreateDomain("Nancy", new Evidence(), setup);
domain.ExecuteAssembly(@"Path to your nancy app exe");
AppDomain.Unload(domain);
}
}
Then start your second (host) application. It will create new app domain and start your nancy application in it. Now you can update your nancy application while host application is running (right in that folder - because of shadow copying, files are not locked). To apply updates - press any key in host application. This will tear down app domain with your old version and create new app domain with new version, without restarting process.
Using this technique you can for example watch directory with your application via FileSystemWatcher
and replace app domain on changes to application files. You can also minimize downtime by first loading new appdomain to the point before starting your nancy host, then tearing down old app domain and then start nancy host in new app domain.
Upvotes: 1
Reputation: 2888
If you are on Windows/IIS you can use MSDeploy to update your web app without downtime. Be aware that it will not keep any in-memory state as it will spin up the new version in a new AppDomain while the old AppDomain will be unloaded.
Upvotes: 0
Reputation: 2888
The only way to unload code is to unload an entire AppDomain. This means that you probably want to to create a new AppDomain for every Assembly that you load dynamically.
This example gives you a starting point on how to create a new AppDomain and how to call code loaded into another AppDomain: https://stackoverflow.com/a/2648592/540832
Upvotes: 2