Background
近段时间一直有Github网友联系我, 咨询关于Nancy支持Hot-plugging代码补丁的事情,于是便有了此篇博客。
去年,我有用到微软的技术栈做一些东西,其中用到了开源的Nancy框架。可惜的是它并不支持Hot-plugging,鉴于此,我阅读它的源码之后,做了一些简单的代码补丁已达到支持热插拔的目的。
_**注意:本补丁并未在生产环境中使用,仅做了热插拔测试,步骤很简单。
Code Patch
SETP 1
File IRouteCache.cs
src/Nancy/Routing/IRouteCache.cs
Add new method
void Refresh ();
File RouteCache.cs
/src/Nancy/Routing/RouteCache.cs
Change RouteCache : Dictionary to ConcurrentDictionary;
Add new lines to class
private readonly INancyContextFactory contextFactory;
private readonly INancyModuleCatalog moduleCatalog;
Add new lines to line 1 of class constructor
this.contextFactory = contextFactory;
this.moduleCatalog = moduleCatalog;
Move the code of line 39-44 to a new method
public void Refresh ()
{
var request = new Request ("GET", "/", "http");
using (var context = contextFactory.Create (request)) {
this.BuildCache (moduleCatalog.GetAllModules (context));
}
}
SETP 2
File IRouteResolver.cs
/src/Nancy/Routing/IRouteResolver.cs
Add new method
void RebuildTireAndCache ();
File DefaultRouteResolver.cs
src/Nancy/Routing/DefaultRouteResolver.cs
Add new method
public void RebuildTireAndCache ()
{
routeCache.Refresh ();
this.BuildTrie ();
}
SETP 3
File IRequestDispatcher.cs
/src/Nancy/Routing/IRequestDispatcher.cs
Add new method
void Update ();
File DefaultRequestDispatcher.cs
src/Nancy/Routing/DefaultRequestDispatcher.cs
Add new method
public void Update ()
{
routeResolver.RebuildTireAndCache ();
}
SETP 4
File INancyBootstrapper.cs
src/Nancy/Bootstrapper/INancyBootstrapper.cs
Add new method
void RegisterModule (Type moduleType);
File NancyBootstrapperBase.cs
src/Nancy/Bootstrapper/NancyBootstrapperBase.cs
Add new method
public abstract void RegisterModule (Type moduleType);
File DefaultNancyBootstrapper.cs
/src/Nancy/DefaultNancyBootstrapper.cs
Add new method
public override void RegisterModule (Type moduleType)
{
// var modules = AppDomainAssemblyTypeScanner
// .TypesOf<INancyModule> (ScanMode.ExcludeNancy)
// .NotOfType<DiagnosticModule> ()
// .Select (t => new ModuleRegistration (t))
// .Where (c => !Modules.Contains ())
// .ToArray ();
var existingModule = Modules.Any (c => c.ModuleType == moduleType);
if (existingModule) {
throw new ArgumentException ("Duplicate NancyModule.");
}
var mr = new ModuleRegistration (moduleType);
var newModules = Modules.ToList ();
newModules.Add (mr);
RegisterModules (this.Container, newModules);
RegisterRequestContainerModules (this.Container, new[] { mr });
}
SETP 5
File INancyEngine.cs
/src/Nancy/INancyEngine.cs Add new method
void Update ();
File NancyEngine.cs
/src/Nancy/NancyEngine.cs Add new method
public void Update ()
{
dispatcher.Update ();
}
SETP 6
Add the code below to your NancyHost, such as Nancy.Hosting.Self
public void AddModuleFromAssemblyPath (string moduleAssemblyPath)
{
var moduleAssembly = Assembly.LoadFrom (moduleAssemblyPath);
AppDomainAssemblyTypeScanner.AddAssembliesToScan (moduleAssembly);
var modules = moduleAssembly.GetExportedTypes ().Where (c => c.IsSubclassOf (typeof(NancyModule)) || c.IsAssignableFrom (typeof(NancyModule)));
foreach (var module in modules)
{
this.bootstrapper.RegisterModule (module);
this.engine.Update ();
}
}
HOW TO USE?
yourHost.AddModuleFromAssemblyPath(yourNewModuleAssemblyPath);