mmbot/mmbot — pull request #110 by antoinne85 (2014-03-27 03:58:32+00:00)
Title: "Hard Reset", Loading Assemblies in Non-Default AppDomain

There's quite a bit of movement in this, so I'll try to be as clear as possible.

These changes started as "wouldn't it be cool if we could download NuGet packages through MMBot?" Which quickly turned into, "wouldn't it be cool if MMBot could load the updated scripts it just downloaded?" Which requires us to load the assemblies into a different AppDomain so that they can be unloaded/reloaded at will. (Once an assembly is loaded into an AppDomain, it's there for the life of the AppDomain.)

So I wrote the NuGet script, then did a bunch of refactoring. Some files got moved around. Most of what was in the mmbot project got moved into a new project MMBot.Bootstrap. There is also a new project called MMBot.Bootstrap.Interfaces.

The intention is that the mmbot project has a way to get to the types in MMBot.Core without having to specifically reference them. So we use MMBot.Bootstrap as a sort of pass-through. We use the MMBot.Bootstrap.Bootstrapper class in the mmbot project to create a new AppDomain, load the MMBot.Bootstrap assembly into that AppDomain, and instantiate an instance of MMBot.Bootstrap.RobotContainer in that AppDomain.

RobotContainer's job is to wrap the execution of a Robot. It's responsible for starting the robot and, when the time comes, letting the Bootstrapper know that it can be disposed of.

The rest of the changes are less severe in nature and mostly revolve around making sure that we have the ability to cancel the execution of the ConsoleAdapter at will and ensure that every long-running process has been dutifully finished before we attempt to unload the AppDomain and restart.

The relevant commands are:
__mmbot update \__
...where \ is the name of a NuGet package, like Chrome.Logging.Log4Net. You can look in the updated template.ini file for how to configure which repositories get scanned and set up aliases for package names.

__mmbot hardreset__
...forces mmbot to reset, reloading all packages and scripts.

It's worth mentioning that MMBot doesn't play nicely with multiple versions of the same package. For instance, if I have MyNamesace.MyScriptsPackage v1.0.0.0 and v1.0.1.0 in the packages folder I get errors about loading the same assembly multiple times (the errors appear in the console, they don't kill MMBot).

_This behavior is not introduced by these changes._ It is pre-existing.

However, I did slightly alter the way we load scripts from packages. There is now a FilterProbedAssemblies method that attempts to identify packages that have multiple versions present and only loads the one with the highest version.

Please have a look and let me know if you need anything.